// cRenderClass.cpp
// 
//////////////////////////////////////////////////////////////////////////////////////////
// includes 
//////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"

//////////////////////////////////////////////////////////////////////////////////////////
// Declarations 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass graphics(SCREEN_WIDTH, SCREEN_HEIGHT);

//////////////////////////////////////////////////////////////////////////////////////////
// cRenderClass() - constructor 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass::cRenderClass(const int w, const int h)
{
	cParticle_num = 0;
	m_sw = w;
	m_sh = h;

	int total_count = w * h * 3;

	m_buffer = new float[total_count];

	for (int i = 0; i < total_count; i++)
	{
		m_buffer[i] = 0;
	}

	m_point_size = 1;
}

//////////////////////////////////////////////////////////////////////////////////////////
// cRenderClass() - destructor 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass::~cRenderClass()
{
}

//////////////////////////////////////////////////////////////////////////////////////////
// loop() - enters game loop
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::loop()
{
	glutMainLoop();
}

void processNormalKeys(unsigned char key, int x, int y)
{
	switch (key)
	{
	case '+':
	{
		keyy = !keyy;
	}
	break;

	}
}
void processSpecialKeys(int key, int x, int y)
{
	switch (key)
	{
	case GLUT_KEY_F1:
	{
		keyy = !keyy;
	}
	break;
	}
}
void mouseFunc(int button, int state, int mouse_x, int mouse_y)
{
	if (state == GLUT_UP)
	{
		keyy = !keyy;
	}
}
void passiveMotionFunc(int mouse_x, int mouse_y)
{
}

//////////////////////////////////////////////////////////////////////////////////////////
// initialize glut stuff
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::create(int argc, _TCHAR* argv[])
{
	// Initialize glut Library
	glutInit(&argc, (char**)argv);

	// Set initial display mode: double precision, RGB, depth cache
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

	// Set initial window position (100100) pixels
	glutInitWindowPosition(100, 100);

	// Set the initial window size to 500 * 500 pixels
	glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);

	// Create a window called "Wow!"
	glutCreateWindow("Wow!");
	// keyboard callback

	glutKeyboardFunc(processNormalKeys);
	// speacial keys callback
	glutSpecialFunc(processSpecialKeys);
	// mouse callback
	glutMouseFunc(mouseFunc);
	// passive mouse motion callback function
	glutPassiveMotionFunc(passiveMotionFunc);

	// Set callback function for window size change
	glutReshapeFunc(winReshapeFunc);

	// Set redraw function
	glutDisplayFunc(renderScene1);//  important
	//glutDisplayFunc(renderScene2);

	// Set the function to execute when the event loop is idle
	glutIdleFunc(update);
}

//////////////////////////////////////////////////////////////////////////////////////////
// clear() - clears out the render buffer 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::clear()
{
	memset(m_buffer, 0, sizeof(float) * m_sw * m_sh * 3);
}

//////////////////////////////////////////////////////////////////////////////////////////
// setPointSize() - set the pixel size 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::setPointSize(int size)
{
	m_point_size = size;
}

/************************
 After setting the color and the size of the origin, draw a dot at (x, y) position
************************/
void cRenderClass::drawPixel(int x, int y)
{
	//Calculate the range of dots
	int start, end;
	start = -(m_point_size / 2);
	end = (int)((m_point_size / 2.0f) + 0.5);

	for (int i = start; i < end; i++)
	{
		for (int j = start; j < end; j++)
		{
			if ((x + j < 0) || (x + j >= m_sw))   //The x-axis is limited in the range of (0 ~ m_sw)
				continue;

			if ((y + i < 0) || (y + i >= m_sh))   //The y-axis is limited to the range of£¨0~m_sh£©
				continue;

			m_buffer[(((y + i) * m_sw + (x + j)) * 3) + 0] = m_colour.r;
			m_buffer[(((y + i) * m_sw + (x + j)) * 3) + 1] = m_colour.g;
			m_buffer[(((y + i) * m_sw + (x + j)) * 3) + 2] = m_colour.b;
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
// render() - renders this buffer to screen 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::render()
{
	// Clear the color buffer (the background color of the window) and use it with glclearcolor or glcleardepth
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//Draw pixels to screen: width, height, RGB color format, float type, color buffer
	glDrawPixels(m_sw, m_sh, GL_RGB, GL_FLOAT, m_buffer);

	// Function to realize double buffer, function: two buffer pointer exchange
	glutSwapBuffers();

	clear();
}

//////////////////////////////////////////////////////////////////////////////////////////
// setColour() - sets the current colour 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::setColour(float r, float g, float b)
{
	m_colour.r = r;
	m_colour.g = g;
	m_colour.b = b;
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// winReshapeFunc() - gets called initially and whenever the window get resized
// resizing has been locked
//////////////////////////////////////////////////////////////////////////////////////////
void winReshapeFunc(GLint w, GLint h)
{
	// specify current matrix
	glMatrixMode(GL_PROJECTION);
	// load an identity matrix
	glLoadIdentity();

	// create a projection matrix... i.e. 2D projection onto xy plane
	glOrtho(-SCREEN_WIDTH, SCREEN_WIDTH, -SCREEN_HEIGHT, SCREEN_HEIGHT, -100, 100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// set up the viewport
	glViewport
	(
		0,				// lower left x position
		0,				// lower left y position
		(GLsizei)SCREEN_WIDTH,	// viewport width
		(GLsizei)SCREEN_HEIGHT	// viewport height
	);
}

void cRenderClass::new_cParticle()
{
	if (cParticle_num == cParticle_Max)   //If the count reaches the maximum, no new point will be added
	{
		return;
	}

	cParticle_buff[cParticle_num] = new cParticle();  //New point
	cParticle_num++;                                  //Counting plus one
}
void cRenderClass::delet_cParticle(int num)
{
	delete(cParticle_buff[num]);                   //Delete point
	cParticle_num--;                               //Counting minus one

	for (int i = num; i < cParticle_num; i++)      //Point information translation
	{
		cParticle_buff[i] = cParticle_buff[i + 1];
	}
}
int cRenderClass::get_num()
{
	return cParticle_num;
}
cParticle* cRenderClass::get_cParticle(int num)
{
	return cParticle_buff[num];
}
