////////////////////////////////////
// CGLUT.h for BCC Skelton
// GLUT乮OpenGL乯僋儔僗掕媊僼傽僀儖
// Copyright (c) May, 2024
//		By Ysama
////////////////////////////////////
#include	<GL\freeglut.h>				//freeglut儔僀僽儔儕傪Windows偱巊偆堊
#pragma comment(lib, "freeglut.lib")

class CGLUT
{
private:
	//僂傿儞僪僂娭楢儊儞僶乕
	HWND m_hWnd = NULL;								//昞帵僂傿儞僪僂僴儞僪儖
	int m_win_no;									//僂傿儞僪僂斣崋
	int m_x = 100;									//昞帵僂傿儞僪僂x埵抲
	int m_y = 100;									//昞帵僂傿儞僪僂y埵抲
	int m_w = 640;									//昞帵僂傿儞僪僂暆
	int m_h = 480;									//昞帵僂傿儞僪僂崅偝
	unsigned int m_mode = GLUT_SINGLE | GLUT_RGBA;	//昞帵僂傿儞僪僂儌乕僪 GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE)
	char m_title[MAX_PATH] = {0};					//昞帵僂傿儞僪僂僞僀僩儖
public:
	//昤夋僆僽僕僃僋僩娭楢
	int m_Obj = 0;									//昤夋僆僽僕僃僋僩斣崋乮0 - 8乯
	bool m_sw = FALSE;								//儚僀傾乕偐丄僜儕僢僪偐偺僼儔僌(Solid - TRUE, Wire - FALSE)
	//gluLookAt娭悢娭楢
	GLdouble m_LA[9] = {0.0, 0.0, 2.0,				//帇揰埵抲(GLdouble) eyex, eyey, eyez,
						0.0, 0.0, 0.0,				//僋儕僢僾暯柺偺拞怱揰(GLdouble) centerx, centery, centerz,
						0.0, 1.0, 0.0};				//傾偭僾儀僋僞乕(GLdouble) upx, upy, upz
	//搳塭朄慖戰
	int m_proj = 0;									//弶婜抣偼gluPerspective娭悢
	//gluPerspective娭悢娭楢
	GLdouble m_fov = 90.0;							//帇栰乮Fiield of view乯偱扨埵偼搙
	GLdouble m_aspect = m_w / m_h;					//廲墶斾乮暆 / 崅偝乯
	GLdouble m_near = 1.0;							//帇揰偐傜嬤僋儕僢僾暯柺傑偱偺嫍棧乮惓乯
	GLdouble m_far = 20.0;							//帇揰偐傜墦僋儕僢僾暯柺傑偱偺嫍棧乮惓乯
	//glFrustum娭悢娭楢
	//拲堄丗m_near偲m_far偼嫟梡
	GLdouble m_left = -1.0;							//僋儕僢僾暯柺嵍嵗昗
	GLdouble m_right = 1.0;							//僋儕僢僾暯柺塃嵗昗
	GLdouble m_bottom = -1.0;						//僋儕僢僾暯柺壓嵗昗
	GLdouble m_top = 1.0;							//僋儕僢僾暯柺忋嵗昗
	//glOrtho娭悢娭楢乮棫曽懱偺嵍塃忋壓慜屻偺拞怱傪暲峴搳塭乯
	//拲堄丗m_left丄m_right丄m_bottomm_top偼嫟梡
	GLdouble m_front = 1.0;							//庤慜僋儕僢僾暯柺嵗昗
	GLdouble m_back = -1.0;							//墱僋儕僢僾暯柺嵗昗
public:
	CGLUT();										//僐儞僗僩儔僋僞乕
	~CGLUT();										//僨僗僩儔僋僞乕
	HWND GethWnd() {return m_hWnd;}
	void SetPos(int x, int y) {m_x = x; m_y = y;}
	void SetSize(int w, int h) {m_w = w; m_h = h;}
	void SetTitle(char* name) {lstrcpy(m_title, name);}
	void SetMode(unsigned int mode) {m_mode = mode;}
	void Enable(GLenum cap) {glEnable(cap);}
	void Disable(GLenum cap) {glDisable(cap);}
	int Create(char*);
	void Display(void(*func)()) {glutDisplayFunc(func);} 
	void ReDisp() {glutPostRedisplay();}
	void SetLA(GLdouble, GLdouble, GLdouble,		//glLookAt偲摨偠
				GLdouble, GLdouble , GLdouble,		//抣傪m_LA攝楍偵曐懚偟丄
				GLdouble, GLdouble, GLdouble);		//LookAt(gluLookAt)傪屇傇
	void LookAt();
	void Color(GLint r, GLint g, GLint b, GLint a = 1) {glColor4i(r, g, b, a);}						//僆乕僶乕儘乕僪乮惍悢堷悢乯
	void Color(GLfloat r, GLfloat g, GLfloat b, GLfloat a = 1.0) {glColor4f(r, g, b, a);}			//僆乕僶乕儘乕僪乮扨惛搙堷悢乯
	void Color(GLdouble r, GLdouble g, GLdouble b, GLdouble a = 1.0) {glColor4d(r, g, b, a);}		//僆乕僶乕儘乕僪乮攞惛搙堷悢乯
	void Clear(GLbitfield mask) {glClear(mask);}	//GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_ACCUM_BUFFER_BIT, GL_STENCIL_BUFFER_BIT
	void ClearCol(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {glClearColor(red, green, blue, alpha);}
	void Transfer(GLdouble x, GLdouble y, GLdouble z) {glTranslated(x, y, z);}
	void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {glRotatef(angle, x, y, z);}		//僆乕僶乕儘乕僪乮扨惛搙堷悢乯
	void Rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) {glRotated(angle, x, y, z);}	//僆乕僶乕儘乕僪乮攞惛搙堷悢乯
	void Scale(GLfloat x, GLfloat y, GLfloat z) {glScalef(x, y, z);}								//僆乕僶乕儘乕僪乮扨惛搙堷悢乯
	void Scale(GLdouble x, GLdouble y, GLdouble z) {glScaled(x, y, z);}								//僆乕僶乕儘乕僪乮攞惛搙堷悢乯
	void Reshape(void(*func)(int, int)) {glutReshapeFunc(func);}
	void Resize(int, int);
	void Refresh();																					//僆乕僶乕儘乕僪乮堷悢側偟乯
	void Idle(void(*func)()) {glutIdleFunc(func);}
	void Mouse(void(*func)(int button, int state, int x, int y)) {glutMouseFunc(func);} 
	void Keyboard(void(*func)(unsigned char key, int x, int y)) {glutKeyboardFunc(func);}
	void Loop() {glutMainLoop();}
	void DrawObject();		//3D僆僽僕僃僋僩昤夋娭悢
};

//僐儞僗僩儔僋僞乕
CGLUT::CGLUT() {

	glutInit(&__argc, __argv);			//void glutInit(int* &argc, char** argv);
	glutInitWindowPosition(m_x, m_y);	//void glutInitWindowPosition(int x, int y);
	glutInitWindowSize(m_w, m_h);		//void glutInitWindowSize(intw, int h);
	glutInitDisplayMode(m_mode);		//void glutInitDisplayMode(unsigned int mode);
}

//僨僗僩儔僋僞乕
CGLUT::~CGLUT() {

}

//昞帵僂傿儞僪僂惗惉
int CGLUT::Create(char* name = NULL) {

	m_win_no = glutCreateWindow("");	//int glutCreateWindow(char * title)	//栠傝抣偼僂傿儞僪僂斣崋
	//GL偺僨僶僀僗僐儞僥僉僗僩僴儞僪儖庢摼
	HDC glDc = wglGetCurrentDC();
	//僂傿儞僪僂僴儞僪儖庢摼
	m_hWnd = WindowFromDC(glDc);
	if(!name)
		if(!m_title)
			SendMessage(m_hWnd, WM_SETTEXT, NULL, (LPARAM)__argv[0]);
		else
			SendMessage(m_hWnd, WM_SETTEXT, NULL, (LPARAM)m_title);
	else {
		lstrcpy(m_title, name);
		SendMessage(m_hWnd, WM_SETTEXT, NULL, (LPARAM)m_title);
	}
}

void CGLUT::SetLA(GLdouble eye_x, GLdouble eye_y, GLdouble eye_z,
					GLdouble center_x, GLdouble center_y, GLdouble center_z,
					GLdouble up_x, GLdouble up_y, GLdouble up_z) {
	m_LA[0] = eye_x; m_LA[1] = eye_y; m_LA[2] = eye_z;
	m_LA[3] = center_x; m_LA[4] = center_y; m_LA[5] = center_z;
	m_LA[6] = up_x; m_LA[7] = up_y; m_LA[8] = up_z;
	LookAt();
}

void CGLUT::LookAt() {
	gluLookAt(m_LA[0], m_LA[1], m_LA[2],
			m_LA[3], m_LA[4], m_LA[5],
			m_LA[6], m_LA[7], m_LA[8]);
}

void CGLUT::Resize(int width, int height) {

	glViewport(0, 0, width, height);	//僂僀儞僪僂慡懱偵昞帵
	glMatrixMode(GL_PROJECTION);		//搳塭曄姺儌乕僪傊
	glLoadIdentity();					//搳塭曄姺偺曄姺峴楍傪扨埵峴楍偱弶婜壔
	switch(m_proj) {
	case 0:	//嘆摟帇搳塭朄侾
		gluPerspective(m_fov, m_aspect, m_near, m_far);	//帇栰妏搙丄廲墶斾丄嬤僋儕僢僾暯柺傑偱偺嫍棧丄墦僋儕僢僾暯柺傑偱偺嫍棧
		LookAt();
		break;
	case 1:	//嘇摟帇搳塭朄俀
		glFrustum(m_left, m_right, m_bottom, m_top, m_near, m_far);	//僋儕僢僾暯柺嵗昗(left, right, bottom, top)丄嬤僋儕僢僾暯柺傑偱偺嫍棧丄墦僋儕僢僾暯柺傑偱偺嫍棧
		LookAt();
		break;
	case 2:	//嘊惓搳塭朄乮墦嬤朄傪娷傑側偄搳塭乯
		glOrtho(m_left, m_right, m_bottom, m_top, m_front, m_back);	//m_left, m_right, m_bottom, m_top, m_front, m_back偱埻傑傟傞棫曽懱傪暲峴搳塭
		break;
	}
	glMatrixMode(GL_MODELVIEW);			//帇栰曄姺丒儌僨儕儞僌曄姺儌乕僪傊
	glLoadIdentity();					//帇栰曄姺丒儌僨儕儞僌曄姺偺曄姺峴楍傪扨埵峴楍偱弶婜壔
}

void CGLUT::Refresh() {

	Resize(m_w, m_h);
}

//3D僆僽僕僃僋僩昤夋娭悢
void CGLUT::DrawObject() {

	switch(m_Obj) {
	default:	//1 - 8埲奜偼0偲側傞
	case 0:		//僥傿乕億僢僩
		if(m_sw)
			glutSolidTeapot(0.5);
		else
			glutWireTeapot(0.5);
		break;
	case 1:		//Cube乮棫曽懱乯
		if(m_sw)
			glutSolidCube(0.5);
		else
			glutWireCube(0.5);
		break;
	case 2:		//Sphere乮媴乯
		if(m_sw)
			glutSolidSphere(0.5, 20, 20);
		else
			glutWireSphere(0.5, 20, 20);
		break;
	case 3:		//Cone乮墌悕乯
		if(m_sw)
			glutSolidCone(0.5, 0.8, 20, 20);
		else
			glutWireCone(0.5, 0.8, 20, 20);
		break;
	case 4:		//Torus (僪乕僫僢僣乯
		if(m_sw)
			glutSolidTorus(0.1, 0.4, 20, 20);
		else
			glutWireTorus(0.1, 0.4, 20, 20);
		break;
	case 5:		//Tetrahedron(4柺懱乯
		if(m_sw)
			glutSolidTetrahedron();
		else
			glutWireTetrahedron();
		break;
	case 6:		//Octahedron(8柺懱乯
		if(m_sw)
			glutSolidOctahedron();
		else
			glutWireOctahedron();
		break;
	case 7:		//Dodecahedron(12柺懱乯
		if(m_sw)
			glutSolidDodecahedron();
		else
			glutWireDodecahedron();
		break;
	case 8:		//Icosahedron(20柺懱乯
		if(m_sw)
			glutSolidIcosahedron();
		else
			glutWireIcosahedron();
		break;
	}
}
