home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include <stdio.h>
-
- #include "ray.h"
-
- struct circle *dvl;
-
- struct dirlist **neighbor;
-
- int *markdir;
-
- initdir()
- {register int o0,o1,d;
- register double l;
- struct point c0,c1;
- register double r0,r1;
- struct circle cir;
- register struct objlist *ol;
- int origins;
- origins=0;
- for(o0=0;o0<maxobj;o0++)
- { if((objects[o0].flags&RAYORIGIN))
- origins++;
- }
- NRECTS=40;
- if(NRECTS*sqrt((double)origins)>100)
- { if(origins)
- NRECTS=100/sqrt((double)origins);
- else
- NRECTS=100;
- }
- if(NRECTS<4)
- NRECTS=4;
- DIRECTIONS=6*NRECTS*NRECTS;
- dvl=nalloc(struct circle,DIRECTIONS);
- neighbor=nalloc(struct dirlist *,DIRECTIONS);
- markdir=nalloc(int,DIRECTIONS);
- candidates=nalloc(struct objlist **,maxobj);
- for(o0=0;o0<maxobj;o0++)
- { if(!(objects[o0].flags&RAYORIGIN))
- continue;;
- candidates[o0]=nalloc(struct objlist *,DIRECTIONS);
- }
- initdvl();
- initneighbor();
- for(d=0;d<DIRECTIONS;d++)
- markdir[d]=0;
- for(o0=0;o0<maxobj;o0++)
- { if(!(objects[o0].flags&RAYORIGIN))
- continue;;
- for(d=0;d<DIRECTIONS;d++)
- candidates[o0][d]=(struct objlist *)0;
- for(o1=lights+1;o1<maxobj;o1++)
- { if(o0==o1)
- continue;
- if(dflag)
- fprintf(stderr,"object %d to %d\n",o0,o1);
- c0=objects[o0].center;
- r0=objects[o0].radius;
- c1=objects[o1].center;
- r1=objects[o1].radius;
- cir.o.x=c1.x-c0.x;
- cir.o.y=c1.y-c0.y;
- cir.o.z=c1.z-c0.z;
- l=sqrt(cir.o.x*cir.o.x+cir.o.y*cir.o.y+cir.o.z*cir.o.z);
- cir.o.x/=l;
- cir.o.y/=l;
- cir.o.z/=l;
- if(r0+r1>=l)
- { for(d=0;d<DIRECTIONS;d++)
- { if(oflag)
- ol=alloc(struct objlist);
- else
- ol=(struct objlist *)
- alloc(struct objlist2);
- ol->obj=o1;
- ol->next=candidates[o0][d];
- if(oflag)
- ol->t=0;
- candidates[o0][d]=ol;
- }
- }
- else
- { cir.s=(r0+r1)/l;
- cir.c=sqrt(1-cir.s*cir.s);
- d=dindex(cir.o);
- if(oflag)
- ttraverse(d,&cir,o1,
- candidates[o0],l-r0-r1);
- else
- traverse(d,&cir,o1,candidates[o0]);
- tclear(d);
- }
- }
- if(oflag)
- for(d=0;d<DIRECTIONS;d++)
- sortlist(candidates[o0][d]);
- }
- if(tflag)
- {int c;
- c=0;
- for(d=0;d<DIRECTIONS;d++)
- for(ol=candidates[0][d];ol;ol=ol->next)
- c++;
- fprintf(stderr,"Image complexity %g\n",((double)c)/DIRECTIONS);
- for(o0=1;o0<lights+1;o0++)
- { c=0;
- for(d=0;d<DIRECTIONS;d++)
- for(ol=candidates[o0][d];ol;ol=ol->next)
- c++;
- fprintf(stderr,"Shadow complexity for light %d %g\n",
- o0,((double)c)/DIRECTIONS);
- }
- }
- }
-
- traverse(d,cir,o,ol)
- register int d;
- register struct circle *cir;
- register int o;
- register struct objlist **ol;
- {register struct dirlist *dl;
- register struct objlist *ol2;
- markdir[d]=1;
- if(!overlap(&dvl[d],cir))
- return;
- ol2=(struct objlist *)alloc(struct objlist2);
- ol2->obj=o;
- ol2->next=ol[d];
- ol[d]=ol2;
- for(dl=neighbor[d];dl;dl=dl->next)
- if(!markdir[dl->dir])
- traverse(dl->dir,cir,o,ol);
- }
-
- ttraverse(d,cir,o,ol,t)
- register int d;
- register struct circle *cir;
- register int o;
- register struct objlist **ol;
- register double t;
- {register struct dirlist *dl;
- register struct objlist *ol2;
- markdir[d]=1;
- if(!overlap(&dvl[d],cir))
- return;
- ol2=alloc(struct objlist);
- ol2->obj=o;
- ol2->next=ol[d];
- ol2->t=t;
- ol[d]=ol2;
- for(dl=neighbor[d];dl;dl=dl->next)
- if(!markdir[dl->dir])
- ttraverse(dl->dir,cir,o,ol,t);
- }
-
- tclear(d)
- register int d;
- {register struct dirlist *dl;
- markdir[d]=0;
- for(dl=neighbor[d];dl;dl=dl->next)
- if(markdir[dl->dir])
- tclear(dl->dir);
- }
-
- overlap(cir0,cir1)
- register struct circle *cir0,*cir1;
- { return
- cir0->o.x*cir1->o.x+cir0->o.y*cir1->o.y+cir0->o.z*cir1->o.z
- >
- cir0->c*cir1->c-cir0->s*cir1->s;
- }
-
- struct circle initdvl2(x,y,z,dx0,dy0,dz0,dx1,dy1,dz1)
- double x,y,z,dx0,dy0,dz0,dx1,dy1,dz1;
- {int i;
- double l,c,minc;
- struct vector v[4];
- struct circle cir;
- for(i=0;i<4;i++)
- { v[i].x=x;
- v[i].y=y;
- v[i].z=z;
- }
- v[1].x+=dx0;
- v[1].y+=dy0;
- v[1].z+=dz0;
- v[2].x+=dx0+dx1;
- v[2].y+=dy0+dy1;
- v[2].z+=dz0+dz1;
- v[3].x+=dx1;
- v[3].y+=dy1;
- v[3].z+=dz1;
- cir.o.x=cir.o.y=cir.o.z=0;
- for(i=0;i<4;i++)
- { cir.o.x+=v[i].x/4;
- cir.o.y+=v[i].y/4;
- cir.o.z+=v[i].z/4;
- l=1/sqrt(v[i].x*v[i].x+v[i].y*v[i].y+v[i].z*v[i].z);
- v[i].x*=l;
- v[i].y*=l;
- v[i].z*=l;
- }
- l=1/sqrt(cir.o.x*cir.o.x+cir.o.y*cir.o.y+cir.o.z*cir.o.z);
- cir.o.x*=l;
- cir.o.y*=l;
- cir.o.z*=l;
- minc=1;
- for(i=0;i<4;i++)
- { c=cir.o.x*v[i].x+cir.o.y*v[i].y+cir.o.z*v[i].z;
- if(c<minc)
- minc=c;
- }
- cir.c=minc*0.999999;
- cir.s=sqrt(1-cir.c*cir.c);
- return cir;
- }
-
- initdvl()
- {int i,j,d;
- double x,y,z,dl;
- dl=2.0/NRECTS;
- d=0;
- x=1;
- z= -1;
- for(i=0;i<NRECTS;i++)
- { y= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,0.0,0.0,dl,0.0,dl,0.0);
- y+=dl;
- }
- z+=dl;
- }
- x= -1;
- z= -1;
- for(i=0;i<NRECTS;i++)
- { y= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,0.0,dl,0.0,0.0,0.0,dl);
- y+=dl;
- }
- z+=dl;
- }
- y=1;
- x= -1;
- for(i=0;i<NRECTS;i++)
- { z= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,dl,0.0,0.0,0.0,0.0,dl);
- z+=dl;
- }
- x+=dl;
- }
- y= -1;
- x= -1;
- for(i=0;i<NRECTS;i++)
- { z= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,0.0,0.0,dl,dl,0.0,0.0);
- z+=dl;
- }
- x+=dl;
- }
- z=1;
- y= -1;
- for(i=0;i<NRECTS;i++)
- { x= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,0.0,dl,0.0,dl,0.0,0.0);
- x+=dl;
- }
- y+=dl;
- }
- z= -1;
- y= -1;
- for(i=0;i<NRECTS;i++)
- { x= -1;
- for(j=0;j<NRECTS;j++)
- { dvl[d++]=initdvl2(x,y,z,dl,0.0,0.0,0.0,dl,0.0);
- x+=dl;
- }
- y+=dl;
- }
- }
-
- struct dirlist *consdir(m,dl)
- int m;
- struct dirlist *dl;
- {struct dirlist *dl2;
- dl2=alloc(struct dirlist);
- dl2->dir=m;
- dl2->next=dl;
- return dl2;
- }
-
- initneighbor()
- {int i;
- double d;
- for(i=0;i<DIRECTIONS;i++)
- neighbor[i]=(struct dirlist *)0;
- d=2.0/NRECTS;
- initneighbor2(1.0,-1.0,-1.0,0.0,d,0.0,0.0,0.0,d);
- initneighbor2(-1.0,-1.0,-1.0,0.0,d,0.0,0.0,0.0,d);
- initneighbor2(-1.0,1.0,-1.0,d,0.0,0.0,0.0,0.0,d);
- initneighbor2(-1.0,-1.0,-1.0,d,0.0,0.0,0.0,0.0,d);
- initneighbor2(-1.0,-1.0,1.0,d,0.0,0.0,0.0,d,0.0);
- initneighbor2(-1.0,-1.0,-1.0,d,0.0,0.0,0.0,d,0.0);
- }
-
- initneighbor2(x,y,z,dx0,dy0,dz0,dx1,dy1,dz1)
- double x,y,z,dx0,dy0,dz0,dx1,dy1,dz1;
- {int i,j,d;
- double x0,y0,z0,x1,y1,z1;
- x0=x+dx0/2+dx1/2;
- y0=y+dy0/2+dy1/2;
- z0=z+dz0/2+dz1/2;
- for(i=0;i<NRECTS;i++)
- { for(j=0;j<NRECTS;j++)
- { x1=x0+i*dx0+j*dx1;
- y1=y0+i*dy0+j*dy1;
- z1=z0+i*dz0+j*dz1;
- d=dindex2(x1,y1,z1);
- neighbor[d]=consdir(dindex2(x1+dx0,y1+dy0,z1+dz0),
- neighbor[d]);
- neighbor[d]=consdir(dindex2(x1-dx0,y1-dy0,z1-dz0),
- neighbor[d]);
- neighbor[d]=consdir(dindex2(x1+dx1,y1+dy1,z1+dz1),
- neighbor[d]);
- neighbor[d]=consdir(dindex2(x1-dx1,y1-dy1,z1-dz1),
- neighbor[d]);
- }
- }
- }
-
- dindex2(x,y,z)
- double x,y,z;
- {struct vector v;
- v.x=x;
- v.y=y;
- v.z=z;
- return dindex(v);
- }
-
- print2(v)
- struct vector *v;
- { if(v->z==0)
- { printf("\tz=0\n");
- return;
- }
- printf("\t%g %g\n",v->x/v->z,v->y/v->z);
- }
- sortlist(ol)
- register struct objlist *ol;
- {register struct objlist *ol2,*ol3;
- double t;
- int obj;
- if(!ol)
- return;
- for(;ol->next;ol=ol->next)
- { ol3=ol;
- for(ol2=ol->next;ol2;ol2=ol2->next)
- if(ol2->t<ol3->t)
- ol3=ol2;
- if(ol!=ol3)
- { t=ol->t;
- ol->t=ol3->t;
- ol3->t=t;
- obj=ol->obj;
- ol->obj=ol3->obj;
- ol3->obj=obj;
- }
- }
- }
-