#include "wx/wx.h"
#include "wx/glcanvas.h"
#include <GL/glu.h>

class HelloApp : public wxApp
{
public:
	bool OnInit();
};

DECLARE_APP(HelloApp)



class HelloFrame : public wxFrame
{
public:
	HelloFrame();
};

class HelloGLCanvas : public wxGLCanvas
{
public:
	HelloGLCanvas(wxWindow *parent, const wxWindowID id, const wxPoint& pos, const wxSize& size);
	void Init();
	void Render();
	void OnPaint(wxPaintEvent& event);
	void OnSize(wxSizeEvent& event);

private:
	// イベント処理するclassはこの宣言が必須
	DECLARE_EVENT_TABLE()
};





// widgetのIDの列挙体。
// 今回はGLCanvas用IDのみ。
// 100で始まってるのは他のサンプルがそうだったからというだけで特に深い理由は無いんだけど、
// 0とかから始めると何か問題が起こるんかな？
enum {
	HELLO_GL_CANVAS = 100,
};


HelloFrame::HelloFrame() :
	wxFrame(0, -1, wxT("test app"))
{
	wxGLCanvas *canvas = new HelloGLCanvas(this, HELLO_GL_CANVAS, wxDefaultPosition, wxDefaultSize);

	CreateStatusBar();
	SetStatusText("hello OpenGL");
}




// イベントをメンバ関数へ接続する
BEGIN_EVENT_TABLE( HelloGLCanvas, wxGLCanvas )
	EVT_SIZE( HelloGLCanvas::OnSize )
	EVT_PAINT( HelloGLCanvas::OnPaint )
END_EVENT_TABLE()

HelloGLCanvas::HelloGLCanvas(wxWindow *parent, const wxWindowID id, const wxPoint& pos, const wxSize& size) :
	wxGLCanvas(parent, id, pos, size)
{
	Init();
}

void HelloGLCanvas::Init()
{
	SetCurrent();

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glShadeModel( GL_SMOOTH );
	glCullFace( GL_BACK );
	glFrontFace( GL_CCW );
	glEnable( GL_CULL_FACE );
	glEnable(GL_DEPTH_TEST);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	float light_pos[] = { 2.0, 2.0, 3.0, 1.0 };
	glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
}

void HelloGLCanvas::Render()
{
	// これが無いと正常に再描画されなかったりする
	wxPaintDC dc(this);

	SetCurrent();

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	int w, h;
	GetClientSize(&w, &h);
	gluPerspective( 60.0, (float)w/(float)h, 1.0, 10000.0 );

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(
		2.0, 2.0, 2.0,
		0.0, 0.0, 0.0,
		0.0, 1.0, 0.0);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBegin(GL_QUADS);
	glNormal3f( 0.0, 0.0, 1.0);
	glVertex3f( 0.5, 0.5, 0.5); glVertex3f(-0.5, 0.5, 0.5);
	glVertex3f(-0.5,-0.5, 0.5); glVertex3f( 0.5,-0.5, 0.5);

	glNormal3f( 0.0, 0.0,-1.0);
	glVertex3f(-0.5,-0.5,-0.5); glVertex3f(-0.5, 0.5,-0.5);
	glVertex3f( 0.5, 0.5,-0.5); glVertex3f( 0.5,-0.5,-0.5);

	glNormal3f( 0.0, 1.0, 0.0);
	glVertex3f( 0.5, 0.5, 0.5); glVertex3f( 0.5, 0.5,-0.5);
	glVertex3f(-0.5, 0.5,-0.5); glVertex3f(-0.5, 0.5, 0.5);

	glNormal3f( 0.0,-1.0, 0.0);
	glVertex3f(-0.5,-0.5,-0.5); glVertex3f( 0.5,-0.5,-0.5);
	glVertex3f( 0.5,-0.5, 0.5); glVertex3f(-0.5,-0.5, 0.5);

	glNormal3f( 1.0, 0.0, 0.0);
	glVertex3f( 0.5, 0.5, 0.5); glVertex3f( 0.5,-0.5, 0.5);
	glVertex3f( 0.5,-0.5,-0.5); glVertex3f( 0.5, 0.5,-0.5);

	glNormal3f(-1.0, 0.0, 0.0);
	glVertex3f(-0.5,-0.5,-0.5); glVertex3f(-0.5,-0.5, 0.5);
	glVertex3f(-0.5, 0.5, 0.5); glVertex3f(-0.5, 0.5,-0.5);
	glEnd();

	SwapBuffers();
}

void HelloGLCanvas::OnPaint(wxPaintEvent&)
{
	Render();
}

void HelloGLCanvas::OnSize(wxSizeEvent& event)
{
	wxGLCanvas::OnSize(event);

	SetCurrent();
	glViewport(0, 0, event.GetSize().GetWidth(), event.GetSize().GetHeight());
}




IMPLEMENT_APP(HelloApp)

bool HelloApp::OnInit()
{
	HelloFrame *frame = new HelloFrame();
	frame->Show(TRUE);
	SetTopWindow(frame);

	return true;
}



