#include "view.h"
#include <stdio.h>

typedef struct{
	double width, height, len1, len2;
	int numSteps;
	double red, green, blue;
} Steps;

void Tab(int n) {
	register int k;
	for(k=0; k<n; ++k) printf("    ");
}

void aStep(Steps *step, Vertex *vertex, FaceList *facelist)
{
	Face *face;
	Shading *s;

	/*create all the vertices for a single step*/
	atPutCoordVertex(vertex,0, 0.0, 0.0,   0.0);
	atPutCoordVertex(vertex,1, step->width, 0.0,   0.0);
	atPutCoordVertex(vertex,2, step->width, step->len1, 0.0);
	atPutCoordVertex(vertex,3, 0.0, step->len2, 0.0);
	atPutCoordVertex(vertex,4, 0.0, 0.0,   step->height);
	atPutCoordVertex(vertex,5, step->width, 0.0, step->height);
	atPutCoordVertex(vertex,6, step->width, step->len1, step->height);
	atPutCoordVertex(vertex,7, 0.0, step->len2, step->height);
	
	face = newFace(vertex,0);
	addToBackFace(face,1);
	addToBackFace(face,5);
	addToBackFace(face,4);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);

	face = newFace(vertex,0);
	addToBackFace(face,3);
	addToBackFace(face,2);
	addToBackFace(face,1);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);

	face = newFace(vertex,1);
	addToBackFace(face,2);
	addToBackFace(face,6);
	addToBackFace(face,5);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);

	face = newFace(vertex,2);
	addToBackFace(face,3);
	addToBackFace(face,7);
	addToBackFace(face,6);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);
	
	face = newFace(vertex,4);
	addToBackFace(face,7);
	addToBackFace(face,3);
	addToBackFace(face,0);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);
	
	face = newFace(vertex,4);
	addToBackFace(face,5);
	addToBackFace(face,6);
	addToBackFace(face,7);
	s = newShading(step->red,step->green,step->blue);
	setShadingOfFace(face,s);
	atPutFaceList(facelist,NEXTFreeFaceList(facelist),face);
}

void createSteps(Steps *step, Vertex *vertex, FaceList *facelist)
{
	Object *firstStepObj,*stepObj,*nextStepObj;
	register int m,n,i;
	double theta, scaleFactor;
	TMatrix scale,rot,tran,mat1,mat;
	
	/*create the first step*/
	m = NEXTFreeFaceList(facelist);
	aStep(step,vertex,facelist);
	n = NEXTFreeFaceList(facelist);
	firstStepObj = stepObj = newObject(facelist,1);
	for(i=m; i<n; ++i) addFaceToObject(stepObj,i);
	
	/*find the rotation angle*/
	theta = atan((step->len1-step->len2)/step->width);
	
	/*find the transformation matrix - scale, rotate and then translate*/
	ZROTATION(rot,theta);
	TRANSLATION(tran,0.0,step->len2,0.0);

	
	for(i=1;i<step->numSteps;++i){
		nextStepObj = cloneObject(stepObj);
		addChildToObject(stepObj,nextStepObj);
		scaleFactor = (double)(i+1)/i;
		SCALING(scale,1.0,1.0,scaleFactor);
		multiplyMatrix(scale.TM,rot.TM,mat1.TM);
		multiplyMatrix(mat1.TM,tran.TM,mat.TM);
		setLocalMatrixOfObject(nextStepObj,&mat);
		stepObj = nextStepObj;
	}
	
	FLATTENObject(firstStepObj);
}

static void printVertex(Vertex *vertex, int i)
{
	Point3D *p;
	p = atVertex(vertex,i);
	Tab(3);
	printf("{ %f, %f, %f }\n", p->x,p->y,p->z);
}
	

void createVIZFile(Steps *steps, Vertex *vertex, FaceList *facelist)
{
	register int i;
	Face *face;
	
	printf("OBJECT {\n");
	Tab(1);
	printf("PATCH ( COLOUR = { %f , %f , %f } ) {\n",steps->red,steps->green,steps->blue);
	
	/*for each face in the facelist*/
	for(i=0; i< NEXTFreeFaceList(facelist); ++i){
		Tab(2);
		printf("POLYSTRIP {\n");
		face = atFaceList(facelist,i);
		/*print out the vertices of this face*/
		traverseFace(face,printVertex);
		Tab(2);
		printf("}\n"); /*end POLYSTRIP*/
	}
	Tab(1);
	printf("}\n"); /*end PATCH*/
	printf("}\n"); /*end OBJECT*/
}

void main(int argc, char *argv[])
{
	Vertex *vertex;
	FaceList *facelist;
	Index *index;
	Tree *t;
	View *view;
	Surface *surface;
	Steps steps;
	Lighting *lighting;
	Light ambient,light;
	register int i,j;
	Face *face;
	
	facelist = newFaceList(2000);
	vertex = newVertex(2000);
	
	steps.width = 30.0;
	steps.height = 10.0;
	steps.len1 = 20.0;
	steps.len2 = 24.0;
	steps.numSteps = 20;
	steps.red = 1.0; steps.green = 1.0; steps.blue = 0.0;
	
	createSteps(&steps,vertex,facelist);
	createVIZFile(&steps,vertex,facelist);

	setIntensityOfLight(&ambient,0.2,0.2,0.2);
	lighting = newLighting(&ambient);

	setPositionOfLight(&light,50.0,1000.0,1000.0);
	setIntensityOfLight(&light,0.5,0.5,0.5);
	addLightToLighting(lighting,&light);

	/*set the plane equations and the lighting*/
	for(i=0;i<NEXTFreeFaceList(facelist);++i){
		setPlaneEqOfFace(atFaceList(facelist,i));
		
		setAmbientLightingOnFace((face=atFaceList(facelist,i)),&AMBIENT(lighting));
		for(j=0;j<NOOfLightsIn(lighting);++j)
			setCentreColourOfFace(face,&LIGHTOf(lighting,j),j);
	}

	index = makeSetFromFaceList(facelist);
	
	t = makeTree(facelist,index);
	
	
	initialiseDrawables();
	
	surface = newSurface(10,10,300,300);
	view = newView(surface);
	
	setVRP(view,50.0,-100.0,68.0);
	setCOP(view,0.0,0.0,-3.0);
	setVUV(view,0.0,0.0,1.0);
	setVPN(view,-0.25,1,0.0);
	
	setClipView(view,1.0,1000.0);
	setVPWindowView(view,-2.0,2.0,-2.0,2.0);
	setView(view);
	displayTreeOnView(view,facelist,t);
	flushDrawable();
	
	delayOnDrawable(GETDrawableOfSurface(surface));
}
	
