ftp.nice.ch/pub/next/graphics/3d/Raytracers.N.bs.tar.gz#/raytracers/ohta/src/initdir.c

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.