#include "StylizedGLWindow.h"
#include "StylizedGUI.h"

#include <windows.h>
#include "GL/gl.h"
#include "GL/glu.h"

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#include <Fl/fl.h>

#define _USE_MATH_DEFINES

#include <math.h>
#include <time.h>

#include "TriMesh.h"
#include "TriMesh_algo.h"

#define FLT_MAX         3.402823466e+38F        /* max value */

#define isfinite( x ) ( x <= FLT_MAX ) 

#define RED 0
#define GREEN 1
#define BLUE 2

vector<TriMesh *> meshes;

// Quick 'n dirty portable random number generator 
static inline float tinyrnd()
{
	static unsigned trand = 0;
	trand = 1664525u * trand + 1013904223u;
	return (float) trand / 4294967296.0f;
}

float feature_size(TriMesh *mesh)
{
	mesh->need_curvatures();
	int nv = (int) mesh->curv1.size();
	int nsamp = min(nv, 500);
                
	vector<float> samples;
	samples.reserve(nsamp * 2);
        
	for (int i = 0; i < nsamp; i++) {
		// Quick 'n dirty portable random number generator  
		static unsigned randq = 0;
		randq = unsigned(1664525) * randq + unsigned(1013904223);

		int ind = int(tinyrnd() * nv);
		samples.push_back(fabs(mesh->curv1[ind]));
		samples.push_back(fabs(mesh->curv2[ind]));
	}
	const float frac = 0.1f;
	const float mult = 0.01f;
	int which = int(frac * samples.size());
	nth_element(samples.begin(), samples.begin() + which, samples.end());
	float f = mult / samples[which];
	if (!isfinite(f)) {
		mesh->need_bsphere();
		f = mesh->bsphere.r;
	}
		
	fprintf(stderr, "Feature size = %f\n", f);
	return f;
}

void colorbyCurvs(TriMesh* tm, float scale, float smooth)
{
	tm->need_curvatures();

	float smoothsigma = smooth;
	
	if (smoothsigma > 0.0f) 
	{
		smoothsigma *= tm->feature_size();
		diffuse_curv(tm, smoothsigma);
	}

	float cscale = 10.0f * scale * feature_size(tm);
	TriMesh::dprintf("Using scale = %f\n", cscale);
	cscale = sqr(cscale);

	int nv = (int)tm->vertices.size();
	tm->colors.resize(nv);

	#pragma omp parallel for
	for (int i = 0; i < nv; i++) 
	{
		float H = 0.5f * (tm->curv1[i] + tm->curv2[i]);
		float K = tm->curv1[i] * tm->curv2[i];
		float h = 4.0f / 3.0f * fabs(atan2(H*H-K,H*H*sgn(H)));
		float s = (float) M_2_PI * atan((2.0f*H*H-K)*cscale);
		tm->colors[i] = Color::hsv(h,s,1.0);
	}
}

//these next two functions were stolen from mesh_view.cc, part of trimesh2.

// Draw triangle strips.  They are stored as length followed by values.
void draw_tstrips(const TriMesh *themesh)
{
	const int *t = &themesh->tstrips[0];
	const int *end = t + themesh->tstrips.size();
	while (likely(t < end)) {
		int striplen = *t++;
		glDrawElements(GL_TRIANGLE_STRIP, striplen, GL_UNSIGNED_INT, t);
		t += striplen;
	}
}


void draw_mesh(int i)
{
	const TriMesh *themesh = meshes[i];

	glPushMatrix();
//	glMultMatrixd(xforms[i]);

	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST);

//	if (draw_2side) {
//		glDisable(GL_CULL_FACE);
//	} else {

		glCullFace(GL_BACK);
		glEnable(GL_CULL_FACE);
//	}

	// Vertices
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT,
			sizeof(themesh->vertices[0]),
			&themesh->vertices[0][0]);

	// Normals
	if (!themesh->normals.empty() /*&& !draw_index*/) {
		glEnableClientState(GL_NORMAL_ARRAY);
		glNormalPointer(GL_FLOAT,
				sizeof(themesh->normals[0]),
				&themesh->normals[0][0]);
	} else {
		glDisableClientState(GL_NORMAL_ARRAY);
	}

	// Colors
	if (!themesh->colors.empty() /* && !draw_falsecolor && !draw_index */) {
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(3, GL_FLOAT,
			       sizeof(themesh->colors[0]),
			       &themesh->colors[0][0]);
	} else {
		glDisableClientState(GL_COLOR_ARRAY);
	}
/*
	//tex coords!
	if(!themesh->texCoords.empty())
	{
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(3, GL_FLOAT,
							sizeof(themesh->texCoords[0]), 
							&themesh->texCoords[0][0]);
		//printf("Booya! %d \n", themesh->texCoords.size());
		//printf("%f\n", themesh->texCoords[0][0]);
	}
	else
	{
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}
*/
	// Main drawing pass
	if (themesh->tstrips.empty()) {
		// No triangles - draw as points
		glPointSize(1);
		glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(themesh->vertices.size()));
		glPopMatrix();
		return;
	}

	draw_tstrips(themesh);
	glDisable(GL_POLYGON_OFFSET_FILL);


	glPopMatrix();
}


// at idle time, this gets called
// it must advance time to the current time step by simulating
// all of the objects
// it also gives the camera a chance to do its user interface
void tvIdler(void* v)
{
	StylizedGLWindow* tv = (StylizedGLWindow*) v;
	if (tv->dasCamera->uiStep())
		tv->damage(1);

	unsigned long t = clock();
	unsigned long dt = t - tv->lastClock;

	tv->lastClock = t;

	//float speedup = static_cast<float>(tv->ui->speedup->value());
	float speedup = 2.0f;

	unsigned long ti = static_cast<unsigned long>(static_cast<float>(dt) * speedup);

	tv->timeT +=  ti;

	tv->damage(1);
}



static float squared(float x){return x*x;}


//////////convolution crap
float gauss(float x, float r)
{
	//if((x < r) && (x >= -r))
		return ((1 / sqrtf(2 * (float)M_PI)) * expf( -(squared(x)) / 2) );
	//else
	//	return 0;
}


//////////////////////////////////////////////

/* 
 * Does 1D resampling. 
 * baseImg is the buffer we're looking thru
 * outImg is the buffer we're convolving into
 * l is the left most place of the src rect
 * h is the right most place of the src rect
 * n is the size of the outimg. In this case, 1024
 * place is where we are (in the place this function doesn't know about)
 */

/* these two functions resampleLine and resampleLineY could be done as 
 * one function, but it's more "clean" this way.*/

void resampleLine(unsigned char* oldImg, unsigned char* outImg, float l, float h, int n, int place, float radius, int multiplier)
{
    float delta = (h - l) / n; //1024 is the width
    float x0 = l + (delta / 2);
    float x;
    float sumR, sumG, sumB;
    float lowerBound, upperBound;
	float totalKernelVals = 0.0f;
	//float r = 1.0f; //radius of the filter

    for(int i = 0; i <= n - 1; i++)
    {
		totalKernelVals = 0.0f;
        sumR = sumG = sumB = 0;
        x = x0 + (i * delta);

        lowerBound = ceilf(x - radius);
        upperBound = floorf(x + radius);

		for( int j = (int)lowerBound; j <= (int)upperBound; j++)
		{
            if( j >= 0 && j <= (h - l))
            {
                int index = (j + (place * (int)(h-l))) * multiplier;

                float filterRet = gauss(x-j, radius);

				totalKernelVals += filterRet;
				
			}
		}

        for( int j = (int)lowerBound; j <= (int)upperBound; j++)
        {
            //commenting this if-statement causes no-lines to appear.
            if( j >= 0 && j <= (h - l))
            {
                int index = (j + (place * (int)(h-l))) * multiplier;

                float filterRet = gauss(x-j, radius);
				filterRet /= totalKernelVals;

                sumR = sumR + oldImg[ index + RED ]* filterRet; 

                sumG = sumG + oldImg[ index + GREEN ]* filterRet; 

                sumB = sumB + oldImg[ index + BLUE ]* filterRet; 
            }
        }
        int index = (i + (place * (n))) * multiplier;

        if(sumR > 255)
            sumR = 255;
        if(sumR < 0)
            sumR = 0;
        outImg[index + RED] = (unsigned char)sumR;


        if(sumG > 255)
            sumG = 255;
        if(sumG < 0)
            sumG = 0;

        outImg[index + GREEN] = (unsigned char)sumG;

        if(sumB > 255)
            sumB = 255;
        if(sumB < 0)
            sumB = 0;
        outImg[index + BLUE] = (unsigned char)sumB;

    }
}
//}}}
//{{{resample Y
void resampleLineY(unsigned char* oldImg, unsigned char* outImg, float l, float h, int n, int place, int nW, float radius, int multiplier)
{
    float delta = (h - l) / 768; //768 is the height
    float y0 = l + (delta / 2);
    float y;
    float sumR, sumG, sumB;
    float lowerBound, upperBound;
	float totalKernelVals = 0.0f;
	//float r = 1.0f; //radius of the filter

    for(int i = 0; i <= n - 1; i++)
    {
		totalKernelVals = 0.0f;
        sumR = sumG = sumB = 0;
        y = y0 + (i * delta);

        lowerBound = ceilf(y - radius);
        upperBound = floorf(y + radius);

        for( int j = (int)lowerBound; j <= (int)upperBound; j++)
        {
			if( j >= 0 && j <= (h - l))
			{
			    int index = ((j * 1024) + place) * multiplier;


                float filterRet = gauss(y-j, radius);
				totalKernelVals += filterRet;
			}
		}
	
		for( int j = (int)lowerBound; j <= (int)upperBound; j++)
		{
            //commenting this if-statement causes no-lines to appear.
            if( j >= 0 && j <= (h - l))
            {

                int index = ((j * 1024) + place)*multiplier;


                float filterRet = gauss(y-j, radius);
				filterRet /= totalKernelVals;

                sumR = sumR + oldImg[ index + RED ]* filterRet; 

                sumG = sumG + oldImg[ index + GREEN ]* filterRet; 

                sumB = sumB + oldImg[ index + BLUE ]* filterRet; 
            }
        }
        int index = ((i * 1024) + place)*multiplier;

        if(sumR > 255)
            sumR = 255;
        if(sumR < 0)
            sumR = 0;
        outImg[index + RED] = (unsigned char)sumR;


        if(sumG > 255)
            sumG = 255;
        if(sumG < 0)
            sumG = 0;

        outImg[index + GREEN] = (unsigned char)sumG;

        if(sumB > 255)
            sumB = 255;
        if(sumB < 0)
            sumB = 0;
        outImg[index + BLUE] = (unsigned char)sumB;
    }
}
//}}}

//{{{ Resample "meta" function
void blur(unsigned char* baseImg, float xl, float xh, float yl, float yh, unsigned char* outImg, int mult)
{

    //make a temp buffer that represents an image that has the width
    //  of the new image, but the height of the old image.
    //unsigned char* tmpBuf = (unsigned char*)calloc(newWidth*oldheight, 4);  
	unsigned char* tmpBuf = (unsigned char*)calloc(1024*768, 3);  

	float r = 5.0f; //radius
    //going down the image
    // resamples the old img into a tmpBuffer that represents an image
    // that is the same height as the input image, but the width of the
    // output image
    for(int row = 0; row < 768; row++)
    {
        resampleLine(baseImg, tmpBuf, xl, xh, 1024, row, r,mult);  
    }

    
    //going across all the columns
    //
    //now using the tmpBuffer (that is oldHeight by newWidth) and 
    //sampling that into the true output image (which is newHeight by
    //oldHeight).
    for(int i = 0; i < 1024; i++)
    {
        //NEEDS to be newheight
        resampleLineY(tmpBuf, outImg, yl, yh, 768, i, 1024, r,mult);
    }
    free(tmpBuf);
}//}}}


////////////////////////


void gradientFilterX(unsigned char* inImg, char* outImg)
{
	int imgSize = 1024*768;//*3;
	int currRow = 0;
	int currCol = 0;
	//unsigned int sumR, sumG, sumB;
	int sum = 0;
	//for the image size
	for(int p = 0; p < imgSize; p++)
	{
		//sumR = sumG = sumB = 0;
		sum = 0;
		currRow = p / (1024 /** 3*/);
		//currCol = p % 1024;
		
		//filtering with [-1 0 1]
		//with clamping at boundaries.

		//if the pixel before this one is on the same row
		if( (p-1)/(1024/**3*/) == currRow)
		{
			if(p != 0){
				sum -= inImg[p - 1];				
			}
			/*
			sumR -= inImg[p - 1 + RED];
			sumG -= inImg[p - 1 + GREEN];
			sumB -= inImg[p - 1 + BLUE];
			*/
		}

		//if the pixel after this one is on the same row...
		if( (p+1)/(1024) == currRow)
		{
			if(p != imgSize){
				sum += inImg[p+1];
			}
			/*
			sumR += inImg[p + 1 + RED];
			sumG += inImg[p + 1 + GREEN];
			sumB += inImg[p + 1 + BLUE];
			*/
		}

		if(sum < -255)
			sum = -255;
		if(sum > 255)
			sum = 255;
		outImg[p] = (char)sum;
	}
}

void gradientFilterY(unsigned char* inImg, char* outImg)
{
	int imgSize = 1024*768;
	int currRow = 0;
	int currCol = 0;
	//unsigned int sumR, sumG, sumB;
	int sum = 0;

	//for the image size
	//loop through all the rows
	for(int col = 0; col < 1024; col++)
	{
		for(int row = 0; row < 768; row++)
		{
			//sumR = sumG = sumB = 0;
			sum = 0;
			int index = (row * 1024) + (col);

			if((index - 1024) >= 0)
			{
			//-1
				sum -= inImg[index - 1024];
				/*
				sumR -= inImg[index-(1024 * 3)+RED];
				sumG -= inImg[index-(1024 * 3)+GREEN];
				sumB -= inImg[index-(1024 * 3)+BLUE];
				*/
			}

			int indexTo2 = index+(1024);
			
			if(indexTo2 < imgSize)
			{
				sum += inImg[index + 1024];
				/*
				//+1
				sumR += inImg[indexTo2+RED];
				sumG += inImg[indexTo2+GREEN];
				sumB += inImg[indexTo2+BLUE];
				*/
			}

			if(sum < -255)
				sum = -255;
			if(sum > 255)
				sum = 255;
			outImg[index] = -1 * (char)sum;
		}
	}
}



void StylizedGLWindow::draw()
{
//	glViewport(0,0,w(),h());

	// clear the window, be sure to clear the Z-Buffer too
	glClearColor(0,0,.3f,0);		// background should be blue
	// we need to clear out the stencil buffer since we'll use
	// it for shadows
	glClearStencil(0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glEnable(GL_DEPTH);

	// Blayne prefers GL_DIFFUSE
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

	// prepare for projection
	setProjection();		// put the code to set up matrices here

	// TODO: you might want to set the lighting up differently
	// if you do, 
	// we need to set up the lights AFTER setting up the projection

	// enable the lighting
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_DEPTH_TEST);


	drawStuff();
	
}



void StylizedGLWindow::setProjection()
{
	glMatrixMode(GL_PROJECTION);
	glViewport(0,0,w(),h());
	glLoadIdentity();

	double aspect = ((double) w()) / ((double) h());
	double FoV = 90.0;
	gluPerspective(FoV, aspect, 10.0f, 6000);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//lights go here
//		glEnable(GL_LIGHTING);
//		glEnable(GL_LIGHT0);
//	//	glEnable(GL_LIGHT1);
//	//	glEnable(GL_LIGHT2);
//
//
//	GLfloat lightPosition1[] = {0,1,1,0}; // {50, 200.0, 50, 1.0};
//	GLfloat lightPosition2[] = {1, 0, 0, 0};
//	GLfloat lightPosition3[] = {0, 1, 0, 0};
//	GLfloat yellowLight[] = {0.5f, 0.5f, .1f, 1.0};
////	GLfloat whiteLight[] = {1.0f, 1.0f, 1.0f, 1.0};
////	GLfloat blueLight[] = {.1f,.1f,1.0f,1.0};
//	GLfloat grayLight[] = {.3f, .3f, .3f, 1.0};
//
//	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition1);
//	//glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteLight);
//	glLightfv(GL_LIGHT0, GL_AMBIENT, grayLight);
//
//	glLightfv(GL_LIGHT1, GL_POSITION, lightPosition2);
//	glLightfv(GL_LIGHT1, GL_DIFFUSE, yellowLight);

	/*
	glLightfv(GL_LIGHT2, GL_POSITION, lightPosition3);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, blueLight);
	*/

	Matrix mat;
	dasCamera->getCamera(mat);
	glMultMatrixf(&mat[0][0]);

}
/*
	Change what we draw based on whether the style is on or off. Should probably 
		import the "togglify" code for those...
*/

void StylizedGLWindow::drawStuff()
{

	if(!doneOnce)
	{
		for(unsigned int i = 0; i < meshes.size(); i++)
		{
			draw_mesh(i);
		}	
	}
	char brush2[16] = {
		0, 2, 1, 0,
		2, 1, 1, 1,
		2, 1, 1, 1,
		0, 2, 1, 0
	};
	char brush4[64] = {
		0, 0, 0, 2, 1, 0, 0, 0,
		0, 0, 2, 1, 1, 1, 0, 0,
		0, 2, 1, 1, 1, 1, 1, 0,
		2, 2, 1, 1, 1, 1, 1, 1,
		2, 2, 1, 1, 1, 1, 1, 1,
		0, 2, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 1, 0, 0, 0
	};
	char brush6[144] = {
		0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	};
	char brush8[256] = {
		0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	};
	char brush10[400] = {
		0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
		2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
		0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	};

	if(sw->stylizeButton->value())
	{
		//we don't want to constantly draw....
		if(!doneOnce)
		{
			printf("YOOGLES!\n");
			doneOnce = 1;

			GLint V[4];
			glGetIntegerv(GL_VIEWPORT, V);
			GLint width = V[2], height = V[3];
			printf("w: %d, h: %d\n", width, height);
			GLint totalSize = width*height*3;
			
			GLfloat* depthBuf = new GLfloat[totalSize];
			
			glReadBuffer(GL_BACK);
			glPixelZoom(1.0f,1.0f);

			glPixelStorei(GL_PACK_ALIGNMENT, 1);
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

			glReadPixels(V[0], V[1], width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthBuf);

			/* ok, read in the color buffer, store in buf */
			unsigned char *readBuf = new unsigned char[totalSize];
			unsigned char *buf = new unsigned char[totalSize];
			unsigned char *paintbuf = new unsigned char[totalSize];

			unsigned char *gradBuf = new unsigned char[totalSize];
			unsigned char *gfX = new unsigned char[totalSize/3];
			unsigned char *gfY = new unsigned char[totalSize/3];

			//if(sw->gaussButton->value())
			//{
			//	glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, readBuf);
			//	blur(readBuf, -.5, 1024-0.5, -0.5, 768-0.5,gradBuf,3);

			//	gradientFilterX(gradBuf, gfX);
			//	gradientFilterY(gradBuf, gfY);

			//	for(int i = 0; i < totalSize; i++)
			//	{	
			//		buf[i] = gradBuf[i];
			//	}
			//}
			//else
			//{
				glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
			//}

			//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
			//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, readBuf);
			//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);

			//blur(readBuf, -.5, 1024-0.5, -0.5, 768-0.5,buf);
			for(int i = 0; i < totalSize; i++)
			{
				onceComputedBuf[i] = buf[i];
				if(sw->sceneBrowser->value() != 1)
					paintbuf[i] = 0;
				else 
					paintbuf[i] = buf[i];
			}

			//HOW TO FLIP THE BUFFER
			// Flip top-to-bottom
			//for (int i = 0; i < height/2; i++) {
			//	char *row1 = buf + 3 * width * i;
			//	char *row2 = buf + 3 * width * (height - 1 - i);
			//	for (int j = 0; j < 3 * width; j++)
			//		swap(row1[j], row2[j]);
			//}


			switch(sw->sceneBrowser->value())
			{

				case 2: //paint outlines
					paintOutlines(height, width, depthBuf, buf,paintbuf);
					break;
				case 3:
					paintBetsy(depthBuf, buf, paintbuf);
					break;
				default:
					paintStuff(height, width, depthBuf, brush2, brush4, brush6,brush8,brush10,buf,paintbuf);
					break;
			}	

			for(int i = 0; i < totalSize; i++){
				onceComputedBuf[i] = paintbuf[i];
			}

			/* then place back on screen. Go us. */
			//glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, paintbuf);

			delete [] buf;
			delete [] paintbuf;
			delete [] depthBuf;
			
		}
		else
		{
//REMEMBER TO FIX ME FOR SERIOUS
			glDrawPixels(1024,768, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);
		}
	}	
}

//The equations for cardinal splines
float StylizedGLWindow::f_cardinal(float u, float p0, float p1, float p2, float p3){
	//set the scale by the tension
	float s = (float)(1 - .5);
	//set the coefficients
	float a0 = p1;
	float a1 = s*(p2 - p0);
	float a2 = (2*s)*p0 + (s-3)*p1 + (3-(2*s))*p2 - s*p3;
	float a3 = -s*p0 + (2-s)*p1 + (s-2)*p2 + s*p3;
	//find f(u)
	return (a0 + a1*u + a2*u*u + a3*u*u*u);
}

void StylizedGLWindow::drawLine(int x1, int y1, int x2, int y2, char red, char green, char blue, unsigned char* paintbuf, int recLimit, float depth)
{
	char* brush;
	int brushsize;

	char brush2[16] = {
		0, 2, 1, 0,
		2, 1, 1, 1,
		2, 1, 1, 1,
		0, 2, 1, 0
	};
	char brush4[64] = {
		0, 0, 0, 2, 1, 0, 0, 0,
		0, 0, 2, 1, 1, 1, 0, 0,
		0, 2, 1, 1, 1, 1, 1, 0,
		2, 2, 1, 1, 1, 1, 1, 1,
		2, 2, 1, 1, 1, 1, 1, 1,
		0, 2, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 1, 0, 0, 0
	};
	char brush6[144] = {
		0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	};
	char brush8[256] = {
		0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	};
	char brush10[400] = {
		0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
		2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
		0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
		0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
		0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
		0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	};

	if(depth > 500){
		brush = brush10;
		brushsize = 20;
	} else if (depth > 250){
		brush = brush4;
		brushsize = 8;
	} else {
		brush = brush2;
		brushsize = 4;
	}


	if(recLimit >= 5 || (x1 == x2 && y1 == y2)) 
	{
		//this is where we actually draw to the buffer
		//int index = y1 * 1024 + x1 * 3;
		
		for(int i = 0; i < brushsize; i++) 
		{
			for(int j = 0; j < brushsize; j++)
			{
				int brushIndex = j * brushsize + i;
				int x = x1 + i - 4;
				int y = y1 + j - 4;
				int paintingIndex = (y * 1024 + x) * 3;
				if (x > 0 && x < 1024 && y > 0 && y < 768) {
					if(brush[brushIndex] == 1 || brush[brushIndex] == 2){						
						paintbuf[paintingIndex] = red;
						paintbuf[paintingIndex+1] = green;
						paintbuf[paintingIndex+2] = blue;
					}
				}
			}
		}
	} else {	
		int midptx = (x1 + x2) / 2;
		int midpty = (y1 + y2) / 2;

		drawLine(x1, y1, midptx, midpty, red, green, blue, paintbuf, recLimit+1, depth);
		drawLine(midptx, midpty, x2, y2, red, green, blue, paintbuf, recLimit+1, depth);
	}
	return;



	////if we get to the end point, paint and return on up.
	//if( (x1 == x2 && y1 == y2 ) || recLimit >= 9)
	//{
	//	//this is where we actually draw to the buffer
	//	//int index = y1 * 1024 + x1 * 3;
	//	
	//	for(int i = 0; i < 8; i++) {
	//		for(int j = 0; j < 8; j++){
	//			int brushIndex = j * 8 + i;
	//			int x = x1 + i - 4;
	//			int y = y1 + j - 4;
	//			int paintingIndex = (y * 1024 + x) * 3;
	//			if (x > 0 && x < 1024 && y > 0 && y < 768) {
	//				if(brush[brushIndex] == 1){						
	//					paintbuf[paintingIndex] = red;
	//					paintbuf[paintingIndex+1] = green;
	//					paintbuf[paintingIndex+2] = blue;
	//				} else if (brush[brushIndex] == 2){			
	//					paintbuf[paintingIndex] = 255;
	//					paintbuf[paintingIndex+1] = 255;
	//					paintbuf[paintingIndex+2] = 255;
	//				} 
	//			}
	//		}
	//	}
	//	return;
	//} else {
	//	//int stopTheRecursion = recLimit++;
	//	int midptx = x1 + x2 / 2;
	//	int midpty = y1 + y2 / 2;
	//	//drawLine(x1, midptx, y1, midpty, red, green, blue, paintbuf, recLimit+1/*!!!!!!!!!*/);
	//	//drawLine(midptx, x2, midpty, y2, red, green, blue, paintbuf, recLimit+1/*!!!!!!!!!*/);
	//	drawLine(x1, y1, midptx, midpty, red, green, blue, paintbuf, recLimit+1/*!!!!!!!!!*/);
	//	drawLine(midptx, midpty, x2, y2, red, green, blue, paintbuf, recLimit+1/*!!!!!!!!!*/);
	//}
	//return;
}

void StylizedGLWindow::drawStroke(vector<int> controlPoints, char red, char green, char blue, unsigned char* paintbuf, float depth)
{
	//create a curve from the control points
	int segments = 10;
	int* drawpoints = new int[segments];
	unsigned int index = 0;
	int p0, p1, p2, p3;
	p0 = p1 = p2 = p3 = 1;

char r = rand() % 255;
char g = rand() % 255;
char b = rand() % 255;

//j = 6, p0 = 14997, p1 = 11913, p2 = 8829, p3 = 5745
//j = 6, p0 = 14997, p1 = 11913, p2 = 8829, p3 = 5745

	if(controlPoints.size() > 4){
		while (index < (controlPoints.size()) - 3){
			p0 = controlPoints[index]/3;
			p1 = controlPoints[index+1]/3;
			p2 = controlPoints[index+2]/3;
			p3 = controlPoints[index+3]/3;/*

				int p0x = p0 % 1024;
				int p0y = p0 / 1024;
				int p1x = p1 % 1024;
				int p1y = p1 / 1024;
				int p2x = p2 % 1024;
				int p2y = p2 / 1024;
				int p3x = p3 % 1024;
				int p3y = p3 / 1024;

			drawLine(p0x, p0y, p1x, p1y, r, g, b, paintbuf, 0);

			if(index == (controlPoints.size()) - 4)
			{
				drawLine(p1x, p1y, p2x, p2y, r, g, b, paintbuf, 0);
				drawLine(p2x, p2y, p3x, p3y, r, g, b, paintbuf, 0);	
			}*/



			for(int j = 0; j < segments; j++){
				//cardinal thingies. Will told me to use the bloody constant, so it's his fault.
				int p0x = p0 % 1024;
				int p0y = p0 / 1024;
				int p1x = p1 % 1024;
				int p1y = p1 / 1024;
				int p2x = p2 % 1024;
				int p2y = p2 / 1024;
				int p3x = p3 % 1024;
				int p3y = p3 / 1024;

				//float x = f_cardinal((float)j/segments, (float)(p0 % 1024), (float)(p1 % 1024), (float)(p2 % 1024), (float)(p3 % 1024));
				//float y = f_cardinal((float)j/segments, (float)(p0 / 1024), (float)(p1 / 1024), (float)(p2 / 1024), (float)(p3 / 1024));
				int x = (int)f_cardinal((float)j/segments, (float)(p0x), (float)(p1x), (float)(p2x), (float)(p3x));
				int y = (int)f_cardinal((float)j/segments, (float)(p0y), (float)(p1y), (float)(p2y), (float)(p3y));
				if(x > 1024){
					x = 1024;
				} else if (x < 0){
					x = 0;
				}
				if(y > 768){
					y = 768;
				} else if (y < 0) {
					y=0;
				}
				int pointIndex = (int) (y * 1024 + x)*3;
				drawpoints[j] = pointIndex;
			}
			//draw out drawpoints.
			for(int k = 0; k < segments - 1; k++) {
				int x1 = drawpoints[k]/3 % 1024;
				int y1 = drawpoints[k]/3 / 1024;
				int x2 = drawpoints[k+1]/3 % 1024;
				int y2 = drawpoints[k+1]/3 / 1024;

				drawLine(x1, y1, x2, y2, red, green, blue, paintbuf,0, depth);/*
paintbuf[drawpoints[k]] = r;
paintbuf[drawpoints[k]+1] = g;
paintbuf[drawpoints[k]+2] = b;
paintbuf[drawpoints[k+1]] = r;
paintbuf[drawpoints[k+1]+1] = g;
paintbuf[drawpoints[k+1]+2] = b;*/
			}
			index++;
		}
	}
}

void StylizedGLWindow::createStroke(int imageHeight, int imageWidth, int startIndex, 
									char* x_gradient, char* y_gradient, unsigned char* buf,
									unsigned char* paintbuf, GLfloat* depthbuf)
{
	int maxPoints = 10;

	vector<int> controlPoints;

	unsigned char red = buf[startIndex] + (rand() % 2 ? 1 : -1) * (rand() % 8);
	unsigned char green = buf[startIndex+1] + (rand() % 2 ? 1 : -1) * (rand() % 8);
	unsigned char blue = buf[startIndex+2] + (rand() % 2 ? 1 : -1) * (rand() % 8);

	GLfloat depthFactor = depthbuf[startIndex/3];
	float farclip = 600;
	float nearclip = 10;
	GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));
	GLfloat depthNormalized = depth / farclip;
	int lastStrokeX = 0;
	int lastStrokeY = 0;

	int nextIndex = startIndex;
	int numPoints = 1;
	controlPoints.push_back(startIndex);
	while(nextIndex != -1 && numPoints < maxPoints)
	{
		//std::cout << "BLAAAAAAAAAAAAAH" << std::endl;
		int gX = x_gradient[nextIndex/3];
		int gY = y_gradient[nextIndex/3];
		int strokeX = -gY;
		int strokeY = gX;

		//is this supposed to happen? Wouldn't this situation just mean the color isn't changing?
		//	I don't think we should simply introduce a false change in color.
		
		while(strokeX == 0 && strokeY == 0) {
			if((lastStrokeX != 0) && (lastStrokeY) != 0){
				strokeX = lastStrokeX;
				strokeY = lastStrokeY;
			} else {
				strokeX = (rand() % 2 ? 1 : -1) * (rand() % 5);
				strokeY = (rand() % 2 ? 1 : -1) * (rand() % 5);
			}
		}

		lastStrokeX = strokeX;
		lastStrokeY = strokeY;

		int nextPointX = ((nextIndex/3) % imageWidth) + strokeX;
		int nextPointY = ((nextIndex/3) / imageWidth) + strokeY;

		if(nextPointX < 0 || nextPointX > imageWidth || nextPointY < 0 || nextPointY > imageHeight){
			nextIndex = -1;
			break;
		} 

		nextIndex = (nextPointY * imageWidth + nextPointX) * 3;

		GLfloat nextDepthFactor = depthbuf[nextIndex/3];
		GLfloat nextDepth = (-2 * nearclip * farclip) / ((nextDepthFactor * (farclip - nearclip)) - (farclip + nearclip));
		GLfloat nextDepthNormalized = nextDepth / farclip;
		GLfloat depthDiff = fabs(depthNormalized - nextDepthNormalized);
		int totalColorDiff = abs(red - buf[nextIndex]) + abs(green - buf[nextIndex+1]) + abs(blue - buf[nextIndex+2]);

		if (depthDiff > .2 || totalColorDiff > 50) {
		//if (depthDiff > .05 || totalColorDiff > 20) {
			nextIndex = -1;
		} else {
			controlPoints.push_back(nextIndex);
		}

		numPoints++;
	}

	drawStroke(controlPoints, red, green, blue, paintbuf, depth);
}

void StylizedGLWindow::paintBetsy(float* depthBuf, /*char* brush2,
									char* brush4, char* brush6, char* brush8, char* brush10,*/ unsigned char* buf,
									unsigned char* paintbuf)
{	
	GLint V[4];
	glGetIntegerv(GL_VIEWPORT, V);
	GLint width = V[2], height = V[3];
	printf("w: %d, h: %d\n", width, height);
	GLint totalSize = width*height*3;

	unsigned char *gradBuf = new unsigned char[totalSize/3];
	char *gfX = new char[totalSize/3];
	char *gfY = new char[totalSize/3];
	unsigned char *readBuf = new unsigned char[totalSize/3];
	
	//jklol we always want this to happen or else Bad Stuff happens when functions farther down try to access
	//	the gradient maps.
	//if(sw->gaussButton->value())
	{
		//so for here we should get the gray-scale image, blur it, then get the gradient filters?
		// set component scales before get pixels
		glPixelTransferf(GL_RED_SCALE, 0.299f);
		glPixelTransferf(GL_GREEN_SCALE, 0.587f);
		glPixelTransferf(GL_BLUE_SCALE, 0.114f);
		glReadPixels(V[0], V[1], width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, readBuf);
		// must restore scales to default values
		glPixelTransferf(GL_RED_SCALE, 1);
		glPixelTransferf(GL_GREEN_SCALE, 1);
		glPixelTransferf(GL_BLUE_SCALE, 1);

		blur(readBuf, -.5, 1024-0.5, -0.5, 768-0.5,gradBuf, 1);

		gradientFilterX(gradBuf, gfX);
		gradientFilterY(gradBuf, gfY);
	}
	
	float farclip = 600;
	float nearclip = 10;

	/* loop through them all... */
	for(int h = 0; h < height; h++) {
		for(int w = 0; w < width-1; w++){
			int currentIndex = (h * width + w) * 3;

			GLfloat depthFactor = depthBuf[currentIndex/3];
			GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));

			if(depth > 500){
				createStroke(height, width, currentIndex, gfX, gfY, buf, paintbuf, depthBuf);
			}
		} //for w
	} //for h
	/* loop through them all... */
	for(int h = 0; h < height; h++) {
		for(int w = 0; w < width-1; w++){
			int currentIndex = (h * width + w) * 3;

			GLfloat depthFactor = depthBuf[currentIndex/3];
			GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));

			if(depth <= 500 && depth >= 250){
				createStroke(height, width, currentIndex, gfX, gfY, buf, paintbuf, depthBuf);
			}
		} //for w
	} //for h
	/* loop through them all... */
	for(int h = 0; h < height; h++) {
		for(int w = 0; w < width-1; w++){
			int currentIndex = (h * width + w) * 3;

			GLfloat depthFactor = depthBuf[currentIndex/3];
			GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));

			if(depth < 250){
				createStroke(height, width, currentIndex, gfX, gfY, buf, paintbuf, depthBuf);
			}
		} //for w
	} //for h
	printf("lolpainted\n");
}

int findNextIndex(int index, unsigned char* colorBuffer, GLfloat* depthBuffer, GLint imageWidth, GLint imageHeight, int originalIndex){
	int i = index / 3;
	int height = i / imageWidth;
	int width = i % imageWidth;
	int nextHeight = height - 1;
	int nextWidth = width - 1;
	int currentIndex = (height * imageWidth + width) * 3;
	GLfloat depthFactor = depthBuffer[height * imageWidth + width];
	//we're lying about the far clipping plane because it looks better
	float farclip = 600;
	float nearclip = 10;

	//Equation yoinked off wikipedia
	GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));
	GLfloat depthNormalized = depth / farclip;	

	for(int h = height - 1; h < height + 1; h++){
		for(int w = width - 1; w < width + 1; w++){
			if(h != height && w != width && h >= 0 && h < imageHeight && w >= 0 && w < imageWidth) {
				int nextIndex = (h * imageWidth + w) * 3;
				GLfloat nextDepthFactor = depthBuffer[h * imageWidth + w];
				GLfloat nextDepth = (-2 * nearclip * farclip) / ((nextDepthFactor * (farclip - nearclip)) - (farclip + nearclip));
				GLfloat nextDepthNormalized = nextDepth / farclip;

				int totalColorDiff = abs(colorBuffer[originalIndex] - colorBuffer[nextIndex]) 
					+ abs(colorBuffer[originalIndex+1] - colorBuffer[nextIndex+1]) + abs(colorBuffer[originalIndex+2] - colorBuffer[nextIndex+2]);
				if(fabs(depthNormalized - nextDepthNormalized) < 0.02f && totalColorDiff < 30){
					return nextIndex;
				}
			}
		}
	}
	return -1;
}

void StylizedGLWindow::paintOutlines(int height, int width, float* depthBuf, unsigned char* buf, unsigned char* paintbuf)
{	
	//char brush2[16] = {
	//	0, 2, 1, 0,
	//	2, 1, 1, 1,
	//	2, 1, 1, 1,
	//	0, 2, 1, 0
	//};
	//char brush4[64] = {
	//	0, 0, 0, 2, 1, 0, 0, 0,
	//	0, 0, 2, 1, 1, 1, 0, 0,
	//	0, 2, 1, 1, 1, 1, 1, 0,
	//	2, 2, 1, 1, 1, 1, 1, 1,
	//	2, 2, 1, 1, 1, 1, 1, 1,
	//	0, 2, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 1, 0, 0, 0
	//};
	//char brush6[144] = {
	//	0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	//};
	//char brush8[256] = {
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	//};
	//char brush10[400] = {
	//	0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
	//	2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
	//	0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	//};

	//if(sw->stylizeButton->value())
	//{
	//	//we don't want to constantly draw....
	//	if(!doneOnce)
	//	{
	//		printf("YOOGLES!\n");
	//		doneOnce = 1;

	//		GLint V[4];
	//		glGetIntegerv(GL_VIEWPORT, V);
	//		GLint width = V[2], height = V[3];
	//		printf("w: %d, h: %d\n", width, height);
	//		GLint totalSize = width*height*3;
	//		
	//		GLfloat* depthBuf = new GLfloat[totalSize];
	//		
	//		glReadBuffer(GL_BACK);
	//		glPixelZoom(1.0f,1.0f);

	//		glPixelStorei(GL_PACK_ALIGNMENT, 1);
	//		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	//		glReadPixels(V[0], V[1], width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthBuf);

	//		/* ok, read in the color buffer, store in buf */
	//		unsigned char *buf = new unsigned char[totalSize];
	//		unsigned char *paintbuf = new unsigned char[totalSize];
	//		unsigned char *readBuf = new unsigned char[totalSize];
	//		unsigned char *gradBuf = new unsigned char[totalSize];
	//		unsigned char *gfY = new unsigned char[totalSize];

	//		if(sw->gaussButton->value())
	//		{
	//			glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, readBuf);
	//			blur(readBuf, -.5, 1024-0.5, -0.5, 768-0.5,gradBuf);
	//			
	//			gradientFilterX(gradBuf, gfY);
	//			gradientFilterY(gfY, buf);
	//		}
	//		else
	//		{
	//			glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
	//		}
	//		//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
	//		//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);

	//		
	//		for(int i = 0; i < totalSize; i++)
	//		{
	//			onceComputedBuf[i] = 0;
	//			paintbuf[i] = 0;
	//		}

			/* loop through them all... */
			for(int h = 0; h < height; h++) {
				for(int w = 0; w < width-1; w++){
					int currentIndex = (h * width + w) * 3;
					//w = w + ( (rand() % 2 ? 1 : -1) * ( rand() % (brushsize/2) ) ) + (brushsize/2);
					char red = buf[currentIndex];// + ((rand() % 2 ? 1 : -1) * (rand() % 5));
					char green = buf[currentIndex+1];// + ((rand() % 2 ? 1 : -1) * (rand() % 5));
					char blue = buf[currentIndex+2];// + ((rand() % 2 ? 1 : -1) * (rand() % 5));
					if(paintbuf[currentIndex] == 0 && paintbuf[currentIndex+1] == 0 && paintbuf[currentIndex+2] == 0){
						int counter = 0;						
						int nextIndex = findNextIndex(currentIndex, buf, depthBuf, width, height, currentIndex);
						while(nextIndex != -1 && counter < width){
							paintbuf[nextIndex] = red;
							paintbuf[nextIndex+1] = green;
							paintbuf[nextIndex+2] = blue;
							nextIndex = findNextIndex(nextIndex, buf, depthBuf, width, height, currentIndex);
							counter++;
						} //while
					} //if
				} //for w
			} //for h

	//		for(int i = 0; i < totalSize; i++){
	//			onceComputedBuf[i] = paintbuf[i];
	//		}

	//		/* then place back on screen. Go us. */
	//		//glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, paintbuf);

	//		delete [] buf;
	//		delete [] paintbuf;
	//		delete [] depthBuf;
	//		
	//	}
	//	else
	//	{
	//		glDrawPixels(1024,768, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);
	//	}
	//}	
}

void StylizedGLWindow::paintStuff(int height, int width, float* depthBuf, char* brush2,
									char* brush4, char* brush6, char* brush8, char* brush10, unsigned char* buf,
									unsigned char* paintbuf)
{	
	//char brush2[16] = {
	//	0, 2, 1, 0,
	//	2, 1, 1, 1,
	//	2, 1, 1, 1,
	//	0, 2, 1, 0
	//};
	//char brush4[64] = {
	//	0, 0, 0, 2, 1, 0, 0, 0,
	//	0, 0, 2, 1, 1, 1, 0, 0,
	//	0, 2, 1, 1, 1, 1, 1, 0,
	//	2, 2, 1, 1, 1, 1, 1, 1,
	//	2, 2, 1, 1, 1, 1, 1, 1,
	//	0, 2, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 1, 0, 0, 0
	//};
	//char brush6[144] = {
	//	0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0,
	//};
	//char brush8[256] = {
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	//	0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0,
	//};
	//char brush10[400] = {
	//	0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
	//	2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	
	//	0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	//	0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	//	0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
	//	0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
	//	0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	//};

	//if(sw->stylizeButton->value())
	//{
	//	//we don't want to constantly draw....
	//	if(!doneOnce)
	//	{
	//		printf("YOOGLES!\n");
	//		doneOnce = 1;

	//		GLint V[4];
	//		glGetIntegerv(GL_VIEWPORT, V);
	//		GLint width = V[2], height = V[3];
	//		printf("w: %d, h: %d\n", width, height);
	//		GLint totalSize = width*height*3;
	//		
	//		GLfloat* depthBuf = new GLfloat[totalSize];
	//		
	//		glReadBuffer(GL_BACK);
	//		glPixelZoom(1.0f,1.0f);

	//		glPixelStorei(GL_PACK_ALIGNMENT, 1);
	//		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	//		glReadPixels(V[0], V[1], width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthBuf);

	//		/* ok, read in the color buffer, store in buf */
	//		unsigned char *readBuf = new unsigned char[totalSize];
	//		unsigned char *buf = new unsigned char[totalSize];
	//		unsigned char *paintbuf = new unsigned char[totalSize];

	//		unsigned char *gradBuf = new unsigned char[totalSize];
	//		unsigned char *gfY = new unsigned char[totalSize];

			unsigned char* tmpBuf = new unsigned char[1024*768*3];
			if(sw->gaussButton->value())
			{
				blur(buf, -.5, 1024-0.5, -0.5, 768-0.5,tmpBuf, 3);

				for(int i = 0; i < 1024*768*3; i++)
					buf[i] = tmpBuf[i];
			}
	//		else
	//		{
	//			glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
	//		}

	//		//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
	//		//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, readBuf);
	//		//glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);

	//		//blur(readBuf, -.5, 1024-0.5, -0.5, 768-0.5,buf);
	//		for(int i = 0; i < totalSize; i++)
	//		{
	//			onceComputedBuf[i] = buf[i];
	//			paintbuf[i] = buf[i];
	//		}

			/* loop through them all... */
			for(int h = 0; h < height; h++) {
				for(int w = 0; w < width; w++){
					GLfloat depthFactor = depthBuf[h * width + w];
					//we're lying about the far clipping plane because it looks better
					float farclip = 600;
					float nearclip = 10;

					//Equation yoinked off wikipedia
					GLfloat depth = (-2 * nearclip * farclip) / ((depthFactor * (farclip - nearclip)) - (farclip + nearclip));
					GLfloat depthNormalized = depth / farclip;

					char* brush;
					int brushsize;

					if(depthNormalized < 0.2){
						brush = brush2;
						brushsize = 4;
					} else if (depthNormalized < 0.4) {
						brush = brush4;
						brushsize = 8;
					} else if (depthNormalized < 0.6) {
						brush = brush6;
						brushsize = 12;
					} else if(depthNormalized < 0.8) {
						brush = brush8;
						brushsize = 16;
					} else {
						brush = brush10;
						brushsize = 20;
					}

					//w = w + rand() % (brushsize/2);
					w = w + ( (rand() % 2 ? 1 : -1) * ( rand() % (brushsize/2) ) ) + (brushsize/2);

					int imageIndex = (h * width + w) * 3;

					for(int k = 0; k < brushsize; k++){
						for(int j = 0; j < brushsize; j++){
							int x = w + k;
							int y = h + j;
							int paintIndex = (y * width + x) * 3;
							if ( x >= 0 && x < width && y >= 0 && y < height){								
								if(brush[j * brushsize + k] == 1) 
								{
									paintbuf[paintIndex] = buf[imageIndex];
									paintbuf[paintIndex+1] = buf[imageIndex+1];
									paintbuf[paintIndex+2] = buf[imageIndex+2];
								} else if(brush[j * brushsize + k] == 2) {
									if((buf[imageIndex] - 10) < 0) {
										paintbuf[paintIndex] = buf[imageIndex];	
									} else {
										paintbuf[paintIndex] = buf[imageIndex] - 10;
									}
									if((buf[imageIndex+1] - 10) < 0) {
										paintbuf[paintIndex+1] = buf[imageIndex+1];				
									} else {
										paintbuf[paintIndex+1] = buf[imageIndex+1] - 10;
									}
									if((buf[imageIndex+2] - 10) < 0) {
										paintbuf[paintIndex+2] = buf[imageIndex+2];				
									} else {
										paintbuf[paintIndex+2] = buf[imageIndex+2] - 10;
									}
								} //else-if
							} //if
						} //for j
					} //for k
				} //for w
			} //for h


	//		for(int i = 0; i < totalSize; i++){
	//			onceComputedBuf[i] = paintbuf[i];
	//		}

	//		/* then place back on screen. Go us. */
	//		//glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, paintbuf);

	//		delete [] buf;
	//		delete [] paintbuf;
	//		delete [] depthBuf;
	//		
	//	}
	//	else
	//	{
	//		glDrawPixels(1024,768, GL_RGB, GL_UNSIGNED_BYTE, onceComputedBuf);
	//	}
	//}	
}



// FlTk Event handler for the window
// TODO: if you want to make the train respond to other events 
// (like key presses), you might want to hack this.
int StylizedGLWindow::handle(int e)
{

	switch(e) {
		case FL_SHOW:
			show();
			return 1;
			/*
		case FL_FOCUS:
			return 1;
		case FL_KEYBOARD:
			return 1;
			*/
		default:
			/* kinda sorta hacky, but it disables the camera from moving around when there's an NPR-ized scene up. */
			if(!doneOnce)
			{
				int r = dasCamera->handle(e);
				if (r) damage(1);
				return r;
			}
			return 1;
	};

}

StylizedGLWindow::StylizedGLWindow(int x, int y, int w, int h, const char* l) : Fl_Gl_Window(x,y,w,h,l), lastClock(clock()),
																timeT(0), doneOnce(0), largestMagnitudeDepth(0), secondLMD(0), modelLoaded(0)
{
	mode( FL_RGB|FL_ALPHA|FL_DOUBLE | FL_STENCIL );

	srand(static_cast<unsigned int>(time(0)));

	Fl::add_idle(tvIdler,this);

	onceComputedBuf = new char[1024*768*3];

	dasCamera = new BetterCamera();
	//hover = new BlenderObj();
	
	
	TriMesh* raptorTM;
	
	raptorTM = TriMesh::read("neptuneFewTris.off");

	raptorTM->need_normals();
	raptorTM->need_tstrips();
	//raptorTM->need_bsphere();

	colorbyCurvs(raptorTM, 20.0f, -1.0f);

	meshes.push_back(raptorTM);

//	printf("size of raptorTM = %d\n", raptorTM->texCoords.size());

	
	TriMesh* objectNumbah2;
	objectNumbah2 = TriMesh::read("hoverjet.obj");
	//objectNumbah2 = TriMesh::read("omninanohexatube.ply");
	objectNumbah2->need_normals();
	objectNumbah2->need_tstrips();
	//objectNumbah2->need_bsphere();
	colorbyCurvs(objectNumbah2, 10.0f, -5.0f);
	meshes.push_back(objectNumbah2);
	srand((int)time(0));
	

	
//	printf("size of objectNumbah2 = %d\n", objectNumbah2->texCoords.size());

	//printf("%f %f %f\n", objectNumbah2->texCoords[0][0],objectNumbah2->texCoords[0][1],objectNumbah2->texCoords[0][2]);

	
}