This is initdir.c in view mode; [Download] [Up]
#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;
}
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.