//
// this file by brian martin 1996
// brian@phyast.pitt.edu
//
// this is part of the source for the MedDLe quake model viewer/editor
//
//

#include"mdl.h"
#include<grdriver.h>

// pre-calculated vertex normals needed to do shading
BG_3pt vertex_normal[162]={
{-0.525731,0.000000,0.850651},
{-0.442863,0.238856,0.864188},
{-0.295242,0.000000,0.955423},
{-0.309017,0.500000,0.809017},
{-0.162460,0.262866,0.951056},
{0.000000,0.000000,1.000000},
{0.000000,0.850651,0.525731},
{-0.147621,0.716567,0.681718},
{0.147621,0.716567,0.681718},
{0.000000,0.525731,0.850651},
{0.309017,0.500000,0.809017},
{0.525731,0.000000,0.850651},
{0.295242,0.000000,0.955423},
{0.442863,0.238856,0.864188},
{0.162460,0.262866,0.951056},
{-0.681718,0.147621,0.716567},
{-0.809017,0.309017,0.500000},
{-0.587785,0.425325,0.688191},
{-0.850651,0.525731,0.000000},
{-0.864188,0.442863,0.238856},
{-0.716567,0.681718,0.147621},
{-0.688191,0.587785,0.425325},
{-0.500000,0.809017,0.309017},
{-0.238856,0.864188,0.442863},
{-0.425325,0.688191,0.587785},
{-0.716567,0.681718,-0.147621},
{-0.500000,0.809017,-0.309017},
{-0.525731,0.850651,0.000000},
{0.000000,0.850651,-0.525731},
{-0.238856,0.864188,-0.442863},
{0.000000,0.955423,-0.295242},
{-0.262866,0.951056,-0.162460},
{0.000000,1.000000,0.000000},
{0.000000,0.955423,0.295242},
{-0.262866,0.951056,0.162460},
{0.238856,0.864188,0.442863},
{0.262866,0.951056,0.162460},
{0.500000,0.809017,0.309017},
{0.238856,0.864188,-0.442863},
{0.262866,0.951056,-0.162460},
{0.500000,0.809017,-0.309017},
{0.850651,0.525731,0.000000},
{0.716567,0.681718,0.147621},
{0.716567,0.681718,-0.147621},
{0.525731,0.850651,0.000000},
{0.425325,0.688191,0.587785},
{0.864188,0.442863,0.238856},
{0.688191,0.587785,0.425325},
{0.809017,0.309017,0.500000},
{0.681718,0.147621,0.716567},
{0.587785,0.425325,0.688191},
{0.955423,0.295242,0.000000},
{1.000000,0.000000,0.000000},
{0.951056,0.162460,0.262866},
{0.850651,-0.525731,0.000000},
{0.955423,-0.295242,0.000000},
{0.864188,-0.442863,0.238856},
{0.951056,-0.162460,0.262866},
{0.809017,-0.309017,0.500000},
{0.681718,-0.147621,0.716567},
{0.850651,0.000000,0.525731},
{0.864188,0.442863,-0.238856},
{0.809017,0.309017,-0.500000},
{0.951056,0.162460,-0.262866},
{0.525731,0.000000,-0.850651},
{0.681718,0.147621,-0.716567},
{0.681718,-0.147621,-0.716567},
{0.850651,0.000000,-0.525731},
{0.809017,-0.309017,-0.500000},
{0.864188,-0.442863,-0.238856},
{0.951056,-0.162460,-0.262866},
{0.147621,0.716567,-0.681718},
{0.309017,0.500000,-0.809017},
{0.425325,0.688191,-0.587785},
{0.442863,0.238856,-0.864188},
{0.587785,0.425325,-0.688191},
{0.688191,0.587785,-0.425325},
{-0.147621,0.716567,-0.681718},
{-0.309017,0.500000,-0.809017},
{0.000000,0.525731,-0.850651},
{-0.525731,0.000000,-0.850651},
{-0.442863,0.238856,-0.864188},
{-0.295242,0.000000,-0.955423},
{-0.162460,0.262866,-0.951056},
{0.000000,0.000000,-1.000000},
{0.295242,0.000000,-0.955423},
{0.162460,0.262866,-0.951056},
{-0.442863,-0.238856,-0.864188},
{-0.309017,-0.500000,-0.809017},
{-0.162460,-0.262866,-0.951056},
{0.000000,-0.850651,-0.525731},
{-0.147621,-0.716567,-0.681718},
{0.147621,-0.716567,-0.681718},
{0.000000,-0.525731,-0.850651},
{0.309017,-0.500000,-0.809017},
{0.442863,-0.238856,-0.864188},
{0.162460,-0.262866,-0.951056},
{0.238856,-0.864188,-0.442863},
{0.500000,-0.809017,-0.309017},
{0.425325,-0.688191,-0.587785},
{0.716567,-0.681718,-0.147621},
{0.688191,-0.587785,-0.425325},
{0.587785,-0.425325,-0.688191},
{0.000000,-0.955423,-0.295242},
{0.000000,-1.000000,0.000000},
{0.262866,-0.951056,-0.162460},
{0.000000,-0.850651,0.525731},
{0.000000,-0.955423,0.295242},
{0.238856,-0.864188,0.442863},
{0.262866,-0.951056,0.162460},
{0.500000,-0.809017,0.309017},
{0.716567,-0.681718,0.147621},
{0.525731,-0.850651,0.000000},
{-0.238856,-0.864188,-0.442863},
{-0.500000,-0.809017,-0.309017},
{-0.262866,-0.951056,-0.162460},
{-0.850651,-0.525731,0.000000},
{-0.716567,-0.681718,-0.147621},
{-0.716567,-0.681718,0.147621},
{-0.525731,-0.850651,0.000000},
{-0.500000,-0.809017,0.309017},
{-0.238856,-0.864188,0.442863},
{-0.262866,-0.951056,0.162460},
{-0.864188,-0.442863,0.238856},
{-0.809017,-0.309017,0.500000},
{-0.688191,-0.587785,0.425325},
{-0.681718,-0.147621,0.716567},
{-0.442863,-0.238856,0.864188},
{-0.587785,-0.425325,0.688191},
{-0.309017,-0.500000,0.809017},
{-0.147621,-0.716567,0.681718},
{-0.425325,-0.688191,0.587785},
{-0.162460,-0.262866,0.951056},
{0.442863,-0.238856,0.864188},
{0.162460,-0.262866,0.951056},
{0.309017,-0.500000,0.809017},
{0.147621,-0.716567,0.681718},
{0.000000,-0.525731,0.850651},
{0.425325,-0.688191,0.587785},
{0.587785,-0.425325,0.688191},
{0.688191,-0.587785,0.425325},
{-0.955423,0.295242,0.000000},
{-0.951056,0.162460,0.262866},
{-1.000000,0.000000,0.000000},
{-0.850651,0.000000,0.525731},
{-0.955423,-0.295242,0.000000},
{-0.951056,-0.162460,0.262866},
{-0.864188,0.442863,-0.238856},
{-0.951056,0.162460,-0.262866},
{-0.809017,0.309017,-0.500000},
{-0.864188,-0.442863,-0.238856},
{-0.951056,-0.162460,-0.262866},
{-0.809017,-0.309017,-0.500000},
{-0.681718,0.147621,-0.716567},
{-0.681718,-0.147621,-0.716567},
{-0.850651,0.000000,-0.525731},
{-0.688191,0.587785,-0.425325},
{-0.587785,0.425325,-0.688191},
{-0.425325,0.688191,-0.587785},
{-0.425325,-0.688191,-0.587785},
{-0.587785,-0.425325,-0.688191}
};


void sort(float v[], int vi[], int left, int right);
void swap(float v[], int vi[], int i, int j);
int frame=0;
int firsttime=1;
int draw_flat=0,ii=5, draw_wire=0, draw_vertices=0;
int draw_gshade=0, draw_textured=0, draw_gtextured=1;
int show_head=0;
int back_color=0;

situation eyeball;
//situation qmodel;
void init_view(MDL_model *);


BG_Polygon mdlpts;
GrContext *vscreen;

int mdl_3d(MDL_model *model, MDL_window *w)
{

	char str[128];
	byte mainloop=1;
	byte cur_key=0;

	FILE *in;

	int i,j,k,l,jj,kk,ll,iii,jjj,kkk;
	int zed=0;
	int dumby,draw_poly;
	int num_screen_pts=0;
	int oldmx, oldmy;
	int y_val;
	int x_val;
	int max_depth=128;
	int update=1;
	int num_screen_sides=0;
	int cycle=0;
	int p1,p2,p3,p4;
	word usi;
	word objects, sides, osides, curblock;
	word prev_y[BG_ScreenWidth];

	unsigned ui,uj,uk,ul;

	long unsigned map_max_x=1024;
	long unsigned map_max_y=1024;

	double forward=0,upward=0,rightward=0;
	double t0,t1,frames, fps;
	double dT=.03;
	double view_angle;
	double u,v;
	double u0,v0,w0;
	double a,b,c,d;
	double aa,bb,cc,dd;
	double front_plane=28.0, back_plane=10000.0, plane_const;
	double z_scale_factor;
	double zadd=5.0;
	double scale_terra=.1;
	struct time t;
	float ftemp;
	int maxn;
	int draw_2d=0;

	// to scale view
	BG_Matrix scaling;
	// the rotation matrices
	BG_Matrix Rx,Ry,Rz;
	BG_Matrix N,T,M,OTemp;
	BG_Matrix M1,M2,M3;
	BG_Matrix E_TM,B_TM,O_TM,Temp_TM,T_TM,TM;

	BG_3pt *framemin, *framemax;
	BG_3pt eye_ptlist[5000];
	float xlist[5000];
	int xindexlist[5000];
	BG_3pt pt1, pt2, pt3, pt4, vect1, vect2, vect3;
	BG_3pt light_ray;
	BG_3pt LR;     // light ray
	BG_3pt MD;     // move direction
	BG_3pt vn[162];


	BG_3pt X_axis,Y_axis, Z_axis;     // move direction

	BG_ScreenCoor pt[4];

	BG_MouseRange(0,0,BG_ScreenWidth,BG_ScreenHeight);



	BG_ClearScreen(0);
	// create a screen buffer in ram to do rendering
	vscreen = GrCreateContext(BG_ScreenWidth,BG_ScreenHeight,NULL,NULL);
	G_buffer = (unsigned  char *)(vscreen->gc_frame.gf_baseaddr[0]);


	if(firsttime==1)init_view(model);
	firsttime=0;

	X_axis.x=10.0;
	X_axis.y=0.0;
	X_axis.z=0.0;
	Y_axis.x=0.0;
	Y_axis.y=10.0;
	Y_axis.z=0.0;
	Z_axis.x=0.0;
	Z_axis.y=0.0;
	Z_axis.z=10.0;

	//Rotation Matrices
	Rx=BG_CalcRx(0);
	Ry=BG_CalcRy(0);
	Rz=BG_CalcRz(0);

	//Scaling matrix
	BG_IdentityMatrix( &scaling );
	//focus=20.0; // ~79 degree total view
	scaling.m[0][0]=focus*(double)(BG_ScreenHeight-1)/win_height;    //scale x
	scaling.m[0][1]=(BG_ScreenWidth/2);
	scaling.m[2][1]=(BG_ScreenHeight/2);
	scaling.m[2][2]=-focus*(double)(BG_ScreenHeight-1)/win_width;    // scale y


	plane_const=(double)USHRT_MAX/((double)back_plane-(double)front_plane);

	BG_MouseToXY(BG_ScreenWidth/2,BG_ScreenHeight/2);
	BG_MouseStatus();
	oldmx=BG_MouseX;
	oldmy=BG_MouseY;

	// direction of light source
	// like sun pointing down
	light_ray.x=.0;
	light_ray.y=-1.0;
	light_ray.z=-1.0;

	a=cos(0);
	b=sin(0);
  /*
   My general prescription for viewing and such:
  1. Get movement of eye, ORI & POS
	a. if moved, then update POS
	b. if rotated, then calc the rotation matrix: Ri=CalcRi(ang)
		 and then rotate ORI: ORI=Ri*ORI
  2. Construct a transformation matrix for the eye: E_TM=SCALE*ORI*POS
  3. Rotate and Move all objects in a similar manner to form
	 the objects transformation matrix: O_TM=O_POS*O_ORI
  4. Construct the final transformation for each object: TM=E_TM*O_TM
	5. Convert Points to eye's coords
	a. make vector,O_P, from origin of object to point of object
	b. new pt in eye frame is P=TM*O_P (all 4 components)
  6. Rotate/Calc side Normals to perform Culling
	a. make side normal,N, in eye coords
	b. make vector from eye origin to a point on the side,EV
	c. if N(dot)EV<0 then draw side
  7. Project the 3d points to the screen
	a. if pt.y>0 then its in front so draw it
	b. get window (screen) coords
		win_x=pt.x/pt.y;
		win_y=pt.z/pt.y;
  8. Draw the polygon using the above points (and clip)
	9. Get input, Calulate, and Repeat

	I should scale like above, but I'm doing it later so i understand the
	math better.
	*/
	int light_move=0;
	update=1;
	cycle=0;
	// main loop
	while(mainloop==1)
	{

		if(kbhit())
		{
			if((cur_key=getch())==0x0)
			{ cur_key=getch();
			switch(cur_key)
			  {
				case ARROW_DOWN:    upward=-1.0; break;
				case ARROW_UP:	    upward=1.0; break;
				case ARROW_LEFT:    {frame--; if(frame<0) frame=(int)model->blocks-1;break;}
				case ARROW_RIGHT:   {frame++; if(frame>=(int)model->blocks) frame=0; break;}
			  }
			}
			else{
			switch(cur_key)
			{
				//case KEY_ENTER:    	mainloop=0; break;
				case 27:	       	mainloop=0; draw_2d=0; break;
				case '1':			mainloop=0; draw_2d=2; break;
				case '2':			mainloop=0; draw_2d=1; break;
				case 'V': case 'v': if(draw_vertices==0) draw_vertices=1; else draw_vertices=0; break;
				case 'T': case 't': if(draw_wire==0) draw_wire=1; else draw_wire=0; break;
				case '\t':
					if(ii==5) {ii=2; draw_flat=1;draw_gshade=0;draw_textured=0;draw_gtextured=0;}
					else if(ii==2) { ii=3; draw_flat=0;draw_gshade=1;draw_textured=0; draw_gtextured=0;}
					else if(ii==3){ ii=4; draw_flat=0;draw_textured=1;draw_gshade=0; draw_gtextured=0;}
					else { ii=5; draw_flat=0;draw_textured=0;draw_gshade=0; draw_gtextured=1;}
				   break;

				case 'h': if(show_head==0) show_head=1; else show_head=0; break;
				case 'c': if(cycle==1) cycle=0; else cycle=1; break;
				case 'b': if(back_color==0) back_color=0x08080808;
						else if(back_color==0x08080808) back_color=0x0F0F0F0F;
						 else back_color=0;
						 break;
		  //		case 'l': if(light_move==0) light_move=1; else light_move=0; break;
				case 'r':
					BG_ZeroMatrix( &model->sit.dir_matrix );
					model->sit.dir_matrix.m[0][0]= 1.0;
					model->sit.dir_matrix.m[1][1]= 1.0;
					model->sit.dir_matrix.m[2][2]= 1.0;
					model->sit.dir_matrix.m[3][3]= 1.0;
					break;

				case ',': case '<': if(model->cur_skin==0) model->cur_skin=model->num_skins-1;
									else model->cur_skin-=1;
									break;
				case '.': case '>': model->cur_skin++;
									if(model->cur_skin==model->num_skins) model->cur_skin=0;
									break;
				case '\"': case '\'': model->bcolor++;
							if(model->bcolor>13)model->bcolor=0;
							break;
				case ';': case ':': model->bcolor--;
							if(model->bcolor<0)model->bcolor=13;
							break;

				case '}': case ']': model->tcolor++;
							if(model->tcolor>13)model->tcolor=0;
							break;
				case '{': case '[': model->tcolor--;
							if(model->tcolor<0) model->tcolor=13;
							break;

				case 's': //screen shot
				{
				 for(i=0;i<100; i++)
				 {
					sprintf(str,"pic%d.bmp",i);
					//see if file exists
					in=fopen(str,"rb");

					if(in==NULL)
					{
						in=fopen(str,"wb");
						BG_WriteBMP(in, pal, G_buffer, BG_ScreenWidth, BG_ScreenHeight);
						fclose(in);
						break;
					}
				 }
				break;
				}
			}
			}
			update=1;
		}

		// check on mouse
		BG_MouseStatus();
		//if not moving light, move object
//		if(light_move==0)
//		{
		if((BG_MouseLeft)&&(BG_MouseX!=oldmx))
		{
			i=(oldmx-BG_MouseX);
			Rz=BG_CalcRz((byte)i);
			model->sit.dir_matrix=BG_MatrixMult(&Rz,&model->sit.dir_matrix);
			zed=1;
			update=1;
		}
		if((BG_MouseRight)&&(BG_MouseY!=oldmy))
		{
			i=(BG_MouseY-oldmy);
			forward=i;
			update=1;
		}
		if((BG_MouseLeft)&&(BG_MouseY!=oldmy))
		{
			i=(oldmy-BG_MouseY);
			Ry=BG_CalcRy((byte)i);
			model->sit.dir_matrix=BG_MatrixMult(&Ry,&model->sit.dir_matrix);
			update=1;
		}
//		}
		// else move light source
//		else
//		{
		if((BG_MouseX!=oldmx)&&(!BG_MouseRight)&&(!BG_MouseLeft))
		{
			i=(oldmx-BG_MouseX);
			Rz=BG_CalcRz((byte)i);
			light_ray =BG_MatrixVector3(&Rz,&light_ray);
			update=1;
		}
		if((BG_MouseY!=oldmy)&&(!BG_MouseRight)&&(!BG_MouseLeft))
		{
			i=(oldmy-BG_MouseY);
			Ry=BG_CalcRy((byte)i);
			light_ray =BG_MatrixVector3(&Ry,&light_ray);
			update=1;
		}


//		}

		if(cycle==1)
		{
			frame++;
			update=1;
			if(frame>=(int)model->blocks) frame=0;
		}

		BG_MouseToXY(BG_ScreenWidth/2,BG_ScreenHeight/2);
		oldmx=BG_ScreenWidth/2;//BG_MouseX;
		oldmy=BG_ScreenHeight/2;//BG_MouseY;

		// if something has changed, redraw screen
		if(update==1)

		{

		MD.x=rightward;
		MD.y=forward;
		MD.z=upward;

		MD=BG_VectorMatrix3(&MD,&eyeball.dir_matrix);

		forward=0;
		upward=0;
		rightward=0;

		eyeball.pos.x+=MD.x;
		if(eyeball.pos.x>=(double)map_max_x) eyeball.pos.x=map_max_x-1;
		if(eyeball.pos.x<0.0) eyeball.pos.x=0;

		eyeball.pos.y+=MD.y;

		if(eyeball.pos.y>=(double)map_max_y) eyeball.pos.y=map_max_y-1;
		if(eyeball.pos.y<0.0) eyeball.pos.y=0;

		eyeball.ix=(unsigned)eyeball.pos.x;
		eyeball.iy=(unsigned)eyeball.pos.y;



		eyeball.pos.z+=MD.z;

		eyeball.pos_matrix.m[0][3]=-eyeball.pos.x;
		eyeball.pos_matrix.m[1][3]=-eyeball.pos.y;
		eyeball.pos_matrix.m[2][3]=-eyeball.pos.z;
		// eye transformation matrix
		E_TM=BG_MatrixMult(&eyeball.dir_matrix,&eyeball.pos_matrix);

		// the light ray
		LR=BG_MatrixVector4(&eyeball.dir_matrix,&light_ray);
		BG_Normalize(&LR);


//***************************************************************************
//***************************************************************************
// draw objects !!!!!!!!!!!!!!!!!!!!!!!!
//***************************************************************************
//***************************************************************************

		// object's transformation matrix
		O_TM=BG_MatrixMult(&model->sit.pos_matrix,&model->sit.dir_matrix);
		// overall transformation matrix
		TM=BG_MatrixMult(&E_TM,&O_TM);
		i=0;
				// put all points in eyeballs coordinates
				for(k=0; k < model->block[frame].num_pts+8; k++)
				{
					eye_ptlist[k]=BG_MatrixVector4(&TM,&model->block[frame].ptlist[k]);
				}
				// put all vertex normals in eye's coords
				for(k=0; k < 162; k++)
				{
					vn[k]=BG_MatrixVector3(&TM,&vertex_normal[k]);
				}
				// find farthest point of each poly from eye.
				for(k=0; k <model->block[frame].num_sides ; k++)
				{
					xlist[k]=-1e23;
					for(l=0; l < 3; l++)
					{
						if(eye_ptlist[model->block[frame].side[k].pt[l]].y>xlist[k])
							xlist[k]=eye_ptlist[model->block[frame].side[k].pt[l]].y;
					}
					xindexlist[k]=k;
				}
				// now sort polys by furthest point
				sort(xlist,xindexlist,0,model->block[frame].num_sides-1);

				G_clear(back_color);
					 // if show header, draw points at bounding box
					 if(show_head)
					 {

							for(k=0;k<8;k++)
							{
							pt1=eye_ptlist[model->block[frame].num_pts+k];
							pt1=BG_MatrixVector4(&scaling,&pt1);
							if((pt1.y>0))//front_plane)&&(pt1.y<back_plane))
							{
								u=pt1.x/pt1.y;
								v=pt1.z/pt1.y;
								mdlpts.x[0]=(int)u;
								mdlpts.x[1]=(int)v;
								G_dot(mdlpts.x,250);

							}
							}

					 }

				//do all sides
				num_screen_sides=0;
				for(k=0; k <model->block[frame].num_sides ; k++)
				{
					num_screen_pts=0;

					// find normals for culling
					pt1=eye_ptlist[model->block[frame].side[xindexlist[k]].pt[0]];
					vect1=BG_MatrixVector3(&TM,&model->block[frame].side[xindexlist[k]].normal);

					// dot normal with a vector which points from the eye to the side
					a = BG_DotProduct(&vect1,&pt1);


					// if in front of eyeball...
					if( a < 0.0 )
					{
						// see how much normal is pointing towards light for flat shading
						if((b= BG_DotProduct(&vect1,&LR)+1.) >2.) b=2.0;
						if(b < 0.) b=0.;
						draw_poly=1;
						// do each point on each side
						for(l=0; l < 3; l++)
						{
							u=0;
							v=0;
							pt1.x=eye_ptlist[model->block[frame].side[xindexlist[k]].pt[l]].x;
							pt1.y=eye_ptlist[model->block[frame].side[xindexlist[k]].pt[l]].y;
							pt1.z=eye_ptlist[model->block[frame].side[xindexlist[k]].pt[l]].z;

							pt1=BG_MatrixVector4(&scaling,&pt1);
							num_screen_sides++;
							// front and back plane clipping
							if((pt1.y>0))//front_plane)&&(pt1.y<back_plane))
							{
								// put points in 2d screen coords
								u=pt1.x/pt1.y;
								v=pt1.z/pt1.y;
								// put data in 3dgpl style for rendering
								mdlpts.x[l*ii]=(int)u;
								mdlpts.x[l*ii+1]=(int)v;

								if(draw_gshade)
								{
									//see how much normal is pointed towards lighgt
									b= 1.-BG_DotProduct(&vn[model->block[frame].nindex[model->block[frame].side[xindexlist[k]].pt[l]]],&LR);
									b=b*.5;
									if(b < 0) b=0;
									// scale intesity from 0 to 15 (different from colormap)
									mdlpts.x[l*3+2]=(int)(15.*(1.-b));//15-(int)(.5*b*15.0);
								}

								if(draw_textured)
								{
									// get coords of texture
									if((model->vertex[3*model->triangle[xindexlist[k]*4+l+1]]==32)
									 &&
									(model->triangle[xindexlist[k]*4]==0))
									{

										mdlpts.x[l*4+2]=model->skinw/2+model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+1];
										mdlpts.x[l*4+3]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+2];
									}
									else
									{
										mdlpts.x[l*4+2]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+1];
										mdlpts.x[l*4+3]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+2];
									}
								}

								if(draw_gtextured)
								{
									// get coords of texture
									if((model->vertex[3*model->triangle[xindexlist[k]*4+l+1]]==32)
									 &&
									(model->triangle[xindexlist[k]*4]==0))
									{

										mdlpts.x[l*5+2]=model->skinw/2+model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+1];
										mdlpts.x[l*5+3]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+2];
									}
									else
									{
										mdlpts.x[l*5+2]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+1];
										mdlpts.x[l*5+3]=model->vertex[3*model->triangle[xindexlist[k]*4+l+1]+2];
									}

									//see how much normal is pointed towards lighgt
									b= 1.-BG_DotProduct(&vn[model->block[frame].nindex[model->block[frame].side[xindexlist[k]].pt[l]]],&LR);
									b=b*.5;
									if(b < 0) b=0;
									// scale intesity from 0 to 15
									mdlpts.x[l*5+4]=(int)(b*15.);//15-(int)(.5*b*15.0);


								}

							}

							else  //don't draw if not in front
							{
								draw_poly=0;
								num_screen_sides--;
								break;
							}

							num_screen_pts++;

						}
						// now call the rendering functs
						if(draw_poly)
						{
							 mdlpts.x[3*ii]=mdlpts.x[0];
							 mdlpts.x[3*ii+1]=mdlpts.x[1];

							 if(draw_flat)
								G_ambient_polygon(mdlpts.x,3,(int)(b*15.0*.5));

							 else if(draw_gtextured)
							 {
								// must set wrap around point
								 mdlpts.x[3*ii+2]=mdlpts.x[2];
								 mdlpts.x[3*ii+3]=mdlpts.x[3];
								 mdlpts.x[3*ii+4]=mdlpts.x[4];
								 G_gtex_poly(mdlpts.x,3,model->skin[model->cur_skin].bitmap,model->skinw, model);
							 }
							 else if(draw_gshade)
							 {
								// must set wrap around point
								 mdlpts.x[3*ii+2]=mdlpts.x[2];
								 G_shaded_polygon(mdlpts.x,3);
							 }
							 else if(draw_textured)
							 {
								// must set wrap around point
								 mdlpts.x[3*ii+2]=mdlpts.x[2];
								 mdlpts.x[3*ii+3]=mdlpts.x[3];
								 G_textured_polygon(mdlpts.x,3,model->skin[model->cur_skin].bitmap,model->skinw, model);
							 }
							 if(draw_wire)
							 {
								G_line(mdlpts.x,mdlpts.x+ii,8);
								G_line(mdlpts.x+ii,mdlpts.x+2*ii,8);
								G_line(mdlpts.x+2*ii,mdlpts.x,8);
							 }
							 if(draw_vertices)
							 {
								l=250;
								G_dot(mdlpts.x,l);
								G_dot(mdlpts.x+ii,l);
								G_dot(mdlpts.x+2*ii,l);
						   }

						}
					}

				}
		// draw some text for some things
		if(light_move==1)
		{
			sprintf(str,"move light");
			MDL_Text(BG_ScreenWidth-90,2,str,253);
		}
		if(show_head)
		{
			sprintf(str,"Frame Name: %s",model->block[frame].name);
			MDL_Text(5,2,str,253);
			sprintf(str,"Frame #: %d",(int)frame);
			MDL_Text(5,10,str,253);
		  /*	sprintf(str,"Bounding Box: %d %d %d : %d %d %d",
			model->frame[frame].sframe.bboxmin.v[0],
			model->frame[frame].sframe.bboxmin.v[1],
			model->frame[frame].sframe.bboxmin.v[2],
			model->frame[frame].sframe.bboxmax.v[0],
			model->frame[frame].sframe.bboxmax.v[1],
			model->frame[frame].sframe.bboxmax.v[2]);
			MDL_Text(5,18,str,253);
			*/
		}
		// use GRX to BitBlt Ram screen buffer to current active video screen
		GrBitBltNC(NULL,0,0,vscreen,0,0,BG_ScreenWidth-1,BG_ScreenHeight-1,GrWRITE);
	}
	update=0;

	}
	// get rid of ram screen buffer
	GrDestroyContext(vscreen);

  // jump to next section
  if(draw_2d==1) return 1;
	else if(draw_2d==2) return 2;
	else return 0;

 }

// sorting routine from  some book. Not the fastest, but it works.
void sort(float v[], int vi[], int left, int right)
{
	int i, last;

	if(left>=right) return;
	swap(v,vi,left,(left+right)/2);
	last=left;
	for(i=left+1; i<=right; i++)
		if(v[i]>v[left])
			swap(v,vi,++last,i);
	swap(v,vi,left,last);
	sort(v,vi,left,last-1);
	sort(v,vi,last+1,right);

}

void swap(float v[], int vi[], int i, int j)
{
	float temp;
	int itemp;

	temp = v[i];
	v[i]=v[j];
	v[j]=temp;
	itemp=vi[i];
	vi[i]=vi[j];
	vi[j]=itemp;
}

// this routine  just sets the initial conditions
void init_view(MDL_model *model)
{
	model->sit.pos.x=0.0;
	model->sit.pos.y=0.0;
	model->sit.pos.z=0.0;
	eyeball.ix=(unsigned)eyeball.pos.x;
	eyeball.iy=(unsigned)eyeball.pos.y;
	eyeball.pos.x=175.0; eyeball.pos.y=0.0; eyeball.pos.z=12.0;
//	model.pos.x=0.0;
//	model.pos.y=0.0;
//	model.pos.z=0.0;
//	eyeball.ix=(unsigned)eyeball.pos.x;
//	eyeball.iy=(unsigned)eyeball.pos.y;

	BG_IdentityMatrix( &eyeball.pos_matrix );
	BG_IdentityMatrix( &model->sit.pos_matrix );
	eyeball.pos_matrix.m[0][3]=eyeball.pos.x;
	eyeball.pos_matrix.m[1][3]=eyeball.pos.y;
	eyeball.pos_matrix.m[2][3]=eyeball.pos.z;
	model->sit.pos_matrix.m[0][3]=model->sit.pos.x;
	model->sit.pos_matrix.m[1][3]=model->sit.pos.y;
	model->sit.pos_matrix.m[2][3]=model->sit.pos.z;
	/*
	Direction matrix:

	 right                  1 0 0 0
	 looking                0 1 0 0
	 up                     0 0 1 0
	 translation            0 0 0 1
	*/

	BG_ZeroMatrix( &eyeball.dir_matrix );
	BG_ZeroMatrix( &model->sit.dir_matrix );
	eyeball.dir_matrix.m[0][1]= 1.0;
	eyeball.dir_matrix.m[1][0]= -1.0;
	eyeball.dir_matrix.m[2][2]= 1.0;
	eyeball.dir_matrix.m[3][3]= 1.0;
	model->sit.dir_matrix.m[0][0]= 1.0;
	model->sit.dir_matrix.m[1][1]= 1.0;
	model->sit.dir_matrix.m[2][2]= 1.0;
	model->sit.dir_matrix.m[3][3]= 1.0;


}