// OknoGLDlg.cpp : implementation file
//

#include "stdafx.h"
#include "OknoGL.h"
#include "OknoGLDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// COknoGLDlg dialog




COknoGLDlg::COknoGLDlg(CWnd* pParent /*=NULL*/)
	: CDialog(COknoGLDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void COknoGLDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(COknoGLDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_CREATE()
//	ON_WM_DESTROY()
ON_WM_DESTROY()
ON_WM_SIZE()
END_MESSAGE_MAP()


// COknoGLDlg message handlers

BOOL COknoGLDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void COknoGLDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
		RysujScene();
		ValidateRect(NULL);
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR COknoGLDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

//----------------------- WGL ------------------------------

bool COknoGLDlg::UstalFormatPikseli(HDC uchwytDC) const
{ 
	PIXELFORMATDESCRIPTOR opisFormatuPikseli; 
	ZeroMemory(&opisFormatuPikseli,sizeof(opisFormatuPikseli)); 
	opisFormatuPikseli.nVersion=1; 
	opisFormatuPikseli.dwFlags=PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; //w oknie, podwojne buforowanie 
	opisFormatuPikseli.iPixelType=PFD_TYPE_RGBA; //typ koloru RGB 
	opisFormatuPikseli.cColorBits=32; //jakosc kolorów 4 bajty
	opisFormatuPikseli.cDepthBits=16; //glebokosc bufora Z (z-buffer) 
	opisFormatuPikseli.iLayerType=PFD_MAIN_PLANE; 
	int formatPikseli=ChoosePixelFormat(uchwytDC,&opisFormatuPikseli); 
	if (formatPikseli==0) return false; 
	if (!SetPixelFormat(uchwytDC,formatPikseli,&opisFormatuPikseli)) return false; 
	return true;
}

bool COknoGLDlg::InitWGL(HWND uchwytOkna)
{
	uchwytDC = ::GetDC(m_hWnd);
	if (!UstalFormatPikseli(uchwytDC)) return false; //Utworzenie kontekstu renderowania i uczynienie go aktywnym
	uchwytRC = wglCreateContext(uchwytDC);
	if (uchwytRC==NULL) return false;
	if (!wglMakeCurrent(uchwytDC, uchwytRC)) return false;			
	return true;
}

void COknoGLDlg::UsunWGL()
{
	wglMakeCurrent(NULL,NULL); 
	wglDeleteContext(uchwytRC); 
	::ReleaseDC(m_hWnd,uchwytDC);
}

//----------------------- OpenGL ------------------------------

#include <gl\gl.h>

void COknoGLDlg::UstawienieSceny(bool rzutowanieIzometryczne) //wartosc domyslna =false
{ 
	CRect obszarUzytkownika;
	this->GetClientRect(&obszarUzytkownika);
	int szerokoscObszaruUzytkownika=obszarUzytkownika.Width();
	int wysokoscObszaruUzytkownika=obszarUzytkownika.Height();

	glViewport(0,0,szerokoscObszaruUzytkownika,wysokoscObszaruUzytkownika); //okno OpenGL = wnetrze formy (domyslnie)
	
	//ustawienie punktu projekcji 
	glMatrixMode(GL_PROJECTION); //przełączenie na macierz projekcji 
	glLoadIdentity(); 
	//left,right,bottom,top,znear,zfar (clipping) 
	float wsp=wysokoscObszaruUzytkownika/(float)szerokoscObszaruUzytkownika;
	if(!rzutowanieIzometryczne)
		//left,right,bottom,top,znear,zfar (clipping) 	
		//mnozenie macierzy rzutowania przez macierz perspektywy - ustalanie frustum 	
		glFrustum(-0.1, 0.1, wsp*-0.1, wsp*0.1, 0.3, 100.0); 
	else
		glOrtho(-3, 3, wsp*-3, wsp*3, 0.3, 100.0);
	glMatrixMode(GL_MODELVIEW); //powrót do macierzy widoku modelu 
	glEnable(GL_DEPTH_TEST); //z-buffer aktywny = ukrywanie niewidocznych powierzchni 
}

void COknoGLDlg::RysujScene() 
{ 
	const float x0=1.0; 
	const float y0=1.0; 
	const float z0=1.0; 
	
	//Przygotowanie bufora 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //czysci bufory 
	glLoadIdentity(); //macierz model-widok = macierz jednostkowa 
	glTranslatef(0.0, 0.0, -10.0); //odsuniecie calosci o 10 
	
	//Rysowanie trojkata 
	glBegin(GL_TRIANGLES); 
	//ustalanie trzech wierzcholkow trojkata (werteksow (x,y,z)) 
	//(0,0,z) jest mniej wiecej w srodku ekranu 
	glVertex3f(-x0, -y0, z0); //dolny lewy 
	glVertex3f(x0, -y0, z0); //dolny prawy 
	glVertex3f(0, y0, z0); //gorny 
	//koniec rysowania figury 
	glEnd(); 
	
	//Z bufora na ekran 
	SwapBuffers(uchwytDC); 
}


int COknoGLDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;

	InitWGL(m_hWnd);
	UstawienieSceny();
	//Wersja OpenGL na pasku tytulu				
	char tytul[1024]="OpenGL ";
	strcat_s(tytul,(char*)glGetString(GL_VERSION));
	this->SetWindowText(tytul);

	return 0;
}

void COknoGLDlg::OnDestroy()
{
	CDialog::OnDestroy();

	UsunWGL();
}

void COknoGLDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	UstawienieSceny();
}
