// Shape.h: interface for the Shape class.
//
//////////////////////////////////////////////////////////////////////

#include "GeomObj.h"

#if !defined(AFX_SHAPE_H__93D8F254_354C_426F_91D5_2B806C6D4AAE__INCLUDED_)
#define AFX_SHAPE_H__93D8F254_354C_426F_91D5_2B806C6D4AAE__INCLUDED_

#ifdef MACOSX
#include <glut.h>
#else
#include <GL/glut.h>
#endif
#include "Scene.h"

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class Extent{
public:
	virtual bool hit(Ray& genRay){return false;}
};

class BoxExtent: public Extent{
private:
	float minX, minY, minZ, maxX, maxY, maxZ;
public:
	BoxExtent(){};
	BoxExtent(float minx, float miny, float minz, float maxx, float maxy, float maxz){
		minX = minx; maxX = maxx;
		minY = miny; maxY = maxy;
		minZ = minz; maxZ = maxz;
	}
	bool hit(Ray& genRay);
	void print();
};

//@@@@@@@@@@@@@@@@@ Shape @@@@@@@@@@@@@@@@@@@@@
class Shape: public GeomObj{
public:
	Material mtrl;
	Shape();
	Affine4 transf,invTransf;
//	virtual Color3 texture(HitInfo& h, int whichTexture);
	void setMaterial(Material& mt);
	void tellMaterialsGL();
	virtual void drawOpenGL(){}
	virtual bool hit(Ray& ray, Intersection& inter){return false;}

}; //end: Shape class


//@@@@@@@@@@@@@@@@@ Sphere @@@@@@@@@@@@@@@@@@@@@
class Sphere : public Shape{
public:
	Sphere(){}
	void drawOpenGL();
	bool hit(Ray& ray, Intersection& inter);
};

//@@@@@@@@@@@@@@@@@ Plane @@@@@@@@@@@@@@@@@@@@@
class Plane : public Shape{
public:
	Plane(){}
	void drawOpenGL();
	bool hit(Ray& ray, Intersection& inter);
};

//@@@@@@@@@@@@@@@@@ TaperedCylinder @@@@@@@@@@@@@@@@@@@@@
class TaperedCylinder : public Shape{
public:
	float smallRadius;
	TaperedCylinder(){}
	void drawOpenGL();
	bool hit(Ray& ray, Intersection& inter);
};

//@@@@@@@@@@@@@@@@@ TaperedCylinder @@@@@@@@@@@@@@@@@@@@@
class Cube : public Shape{
public:
	Cube(){}
	Vector3 cubeNormal(int surf);
	void drawOpenGL();
	bool hit(Ray& ray, Intersection& inter);
};

//################## class VertexID ################
//used to define a Mesh
class VertexID{public: int vertIndex, normIndex;};
//################# class FACE ##############
//used to define a Mesh
class Face{
public:
		int nVerts;
		VertexID * vert; // array of vertex and normal indices
		Face(){ nVerts = 0; vert = NULL;}
		~Face(){delete[] vert; nVerts = 0;}
};
//@$@$@$@$@$@$@$@$@$@ Mesh class @$@$@$@$@$@$@$@$@$
class Mesh : public Shape{
private:
		int numVerts, numNorms, numFaces;
		Point3 *pt; // array of points
		Vector3 *norm; // array of normals
		Face *face; // array of faces
		int lastVertUsed;
		int lastNormUsed;
		int lastFaceUsed;
		BoxExtent Bextent;
		bool triangleHit(Ray& r, Intersection& inter, Point3 v0, Point3 v1, Point3 v2);

public:
		void readMesh(string fname);
		void writeMesh(char* fname);
		void printMesh();
		void drawMesh();
		void drawEdges();
		void freeMesh();
		int isEmpty();
		void makeEmpty();
		Mesh();
		bool hit(Ray& ray, Intersection& inter);
		void drawOpenGL();
		Mesh(string fname);
		Vector3 newell4(int indx[]);
		string meshFileName; // holds file name for this Mesh

}; // end of Mesh class

#endif // !defined(AFX_SHAPE_H__93D8F254_354C_426F_91D5_2B806C6D4AAE__INCLUDED_)
