/* contains the objects to be used in the scene */
#include <windows.h>   // include all the windows headers
#include <windowsx.h>  // include useful macros
#include <stdio.h>
#include <math.h>
#include "headers.h"
extern xyz nor;
double sphere::intersect(xyz *origin,xyz *dir)
{
		double xadj,yadj,zadj,b,t,s;
		xadj=(origin->x)-x;
		yadj=(origin->y)-y;
		zadj=(origin->z)-z;
		b=xadj*dir->x+yadj*dir->y+zadj*dir->z;
		t= b*b-xadj*xadj-yadj*yadj-zadj*zadj+r*r;
		if(t<0) return(0.0);
		s=-b-sqrt(t);
		if(s>0.001) return(s);	/* return smaller solution */
		s=-b+sqrt(t);
		if(s>0.001) return(s);	/* return larger solution */
		return(0.0); /* both solutions negative */
		
	}

void sphere::normal(xyz * hitp,xyz *normal)
{
		
	normal->x=(hitp->x - x) / r;
	normal->y=(hitp->y - y) / r;
	normal->z=(hitp->z - z) / r;

}
xy sphere::get_uv(xyz *hitp)
{
	xy cord;
	xyz pole_pnt,eq_pnt,pole_vec,eq_vec,normal,norm_axis;
	double urad,vrad,u,v;

	pole_pnt.x=x;
	pole_pnt.y=y+r;
	pole_pnt.z=z;

	eq_pnt.x=x+r;
	eq_pnt.y=y;
	eq_pnt.z=z;

	pole_vec.x=pole_pnt.x-x;
	pole_vec.y=pole_pnt.y-y;
	pole_vec.z=pole_pnt.z-z;
	pole_vec.normalize();

	eq_vec.x=eq_pnt.x-x;
	eq_vec.y=eq_pnt.y-y;
	eq_vec.z=eq_pnt.z-z;
	eq_vec.normalize();
//	nor.x=eq_vec.x;
//	nor.y=eq_vec.y;
//	nor.z=eq_vec.z;

	normal.x=(hitp->x - x)/r;
	normal.y=(hitp->y - y)/r;
	normal.z=(hitp->z - z)/r;

	vrad=acosf(-(dot_product(&normal,&pole_vec)));
	v=vrad*0.318309;
	if(v==1||v==0)
		u=0;
	else
	{
		urad=acosf((dot_product(&normal,&eq_vec))/sin(vrad))*0.1591549;
	}
	cross_product(&norm_axis,&pole_vec,&eq_vec);
	if(dot_product(&norm_axis,&normal)>0)
		u=urad;
	else
		u=1-urad;
	cord.x=u;
	cord.y=v;


	return(cord);
}

surface sphere::get_surface()
	{
		return(*s);
	}


double quad::intersect(xyz *origin,xyz *dir)
{
double d,t,vd,vo;
xyz u,v,hit;
xy hit2d;
xy *p[3];
int i,sign=0,next_sign=0,crossing=0;

u.x=pntb.x-pnta.x;
u.y=pntb.y-pnta.y;
u.z=pntb.z-pnta.z;
v.x=pntc.x-pnta.x;
v.y=pntc.y-pnta.y;
v.z=pntc.z-pnta.z;
vd=dot_product(&n,dir);


cross_product(&n,&u,&v);


d=-(n.x*pnta.x+n.y*pnta.y+n.z*pnta.z);
if((fabs(n.x)>fabs(n.y))&&(fabs(n.x)>fabs(n.z)))
{
	max_coefficient=1;
	p1.x=pnta.y;
	p1.y=pnta.z;
	p2.x=pntb.y;
	p2.y=pntb.z;
	p3.x=pntc.y;
	p3.y=pntc.z;
	p4.x=pntd.y;
	p4.y=pntd.z;
}
else if((fabs(n.y)>fabs(n.x))&&(fabs(n.y)>fabs(n.z)))
{
	max_coefficient=2;
	p1.x=pnta.x;
	p1.y=pnta.z;
	p2.x=pntb.x;
	p2.y=pntb.z;
	p3.x=pntc.x;
	p3.y=pntc.z;
	p4.x=pntd.x;
	p4.y=pntd.z;
}
else
{
	max_coefficient=3;
	p1.x=pnta.x;
	p1.y=pnta.y;
	p2.x=pntb.x;
	p2.y=pntb.y;
	p3.x=pntc.x;
	p3.y=pntc.y;
	p4.x=pntd.x;
	p4.y=pntd.y;
}


if(vd==0)
return(0.0);
vo=-(dot_product(&n,origin)+d);
t=vo/vd;
if(t<0)
return(0.0);
hit.x=origin->x+t*dir->x;
hit.y=origin->y+t*dir->y;
hit.z=origin->z+t*dir->z;
if(max_coefficient==1)
{
	hit2d.x=hit.y;
	hit2d.y=hit.z;

}
else if(max_coefficient==2)
{
	hit2d.x=hit.x;
	hit2d.y=hit.z;
}
else
{
	hit2d.x=hit.x;
	hit2d.y=hit.y;
}

p1.x=p1.x-hit2d.x;
p1.y=p1.y-hit2d.y;
p2.x=p2.x-hit2d.x;
p2.y=p2.y-hit2d.y;
p3.x=p3.x-hit2d.x;
p3.y=p3.y-hit2d.y;
p4.x=p4.x-hit2d.x;
p4.y=p4.y-hit2d.y;
p[0]=&p1;
p[1]=&p2;
p[2]=&p3;
p[3]=&p4;
for(i=0;i<4;i++)
{
	if(p[i]->y>=0)
		sign=1;
	else
		sign=-1;

	if(p[(i+1)%4]->y>=0)
		next_sign=1;
	else
		next_sign=-1;

	if(sign != next_sign)
	{
		if(((p[i]->x)>=0)&&(p[(i+1)%4]->x>=0))
		{
			crossing=crossing+1;
		}
		else if(((p[i]->x)<0)&&(p[(i+1)%4]->x<0))
		{}
		else
		{
			if(((p[i]->x - p[i]->y) *( p[(i+1)%4]->x - p[i]->x) / (p[(i+1)%4]->y - p[i]->y))>0)
				crossing=crossing+1;
		}
	}
}
if(crossing%2==0)
	return(0.0);
 else
   return(t);
 }


surface quad::get_surface()
	{
		return(*s);
	}

void quad::normal(xyz * hitp,xyz *normal)
{
		
	normal->x=n.x;
	normal->y=n.y;
	normal->z=n.z;
	normal->normalize();


}

xy quad::get_uv(xyz *hit)
{

xyz pa,pb,pc,pd;
xyz p01,p11,p10,p00;
p01=pnta;
p11=pntb;
p10=pntc;
p00=pntd;
pa=p00-p10+p11-p01;
pb=p10-p00;
pc=p01-p00;
pd=p00;
xyz na,nc,qux,quy;
cross_product(&nc,&pc,&n);
cross_product(&na,&pa,&n);
double du0,du1,du2,a,b,c,dux,duy,ka,kb,sq,de,nu,u,v;
du0=dot_product(&nc,&pd);
du1=dot_product(&na,&pd)+dot_product(&nc,&pb);
du2=dot_product(&na,&pb);
a=du2;
b=du1-dot_product(hit,&na);
c=du0-dot_product(hit,&nc);

if(du2!=0)
{
qux = (na/(2*du2));
dux = -du1/(2*du2);
quy = (-nc)/du2;
duy= du0/du2;


double u0,u1;
ka=dux+dot_product(&qux,hit);
kb=duy+dot_product(&quy,hit);
double sq=sqrt((ka*ka)-kb);
u0=ka-sq;
u1=ka+sq;
if(u0<=1&&u0>=0)
	u=u0;
else if(u1<=1&&u1>=0)
	u=u1;
else u=0;

}
else
{
 nu=	dot_product(&nc,hit)-du0;
 de=  du1-dot_product(&na,hit);
u=nu/de;

}

//start for v
double dv0,dv1,dv2,dvx,dvy,v0,v1;
xyz nb,qvx,qvy;
cross_product(&nb,&pb,&n);
dv0=dot_product(&nb,&pd);
dv1=dot_product(&na,&pd)+dot_product(&nb,&pc);
dv2=dot_product(&na,&pc);

if(dv2!=0)
{
qvx=na/(2*dv2);
dvx=(-dv1)/(2*dv2);
qvy= (-nb)/dv2;
dvy=dv0/dv2;

ka=dvx+dot_product(&qvx,hit);
kb=dvy+dot_product(&qvy,hit);
sq=sqrt((ka*ka)-kb);
v0=ka-sq;
v1=ka+sq;
if(v0<=1&&v0>=0)
	v=v0;
else if(v1<=1&&v1>=0)
	v=v1;
else
v=0;

}
else
{
 nu=	dot_product(&nb,hit)-dv0;
 de=  dv1-dot_product(&na,hit);
v=nu/de;

}
xy cord;
cord.x=u;
cord.y=v;
nor.x=u;
nor.y=v;

return(cord);
}