#pragma once

#pragma warning(disable : 4995)
#include "stdafx.h"
#include <gl\GL.h>
#include <gl\GLU.h>
#include <vector>

using namespace std;

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")

//Struktura przechowujaca pojedynczy vertex.
struct Vertex
{
	//Wspolrzedne vertexu.
	float x;
	float y; 
	float z;
};

//Klasa wektora 3D.
class Vector3
{
public:
	//Wspolrzedne wektora.
	float x;
	float y;
	float z;

	//Konstruktory.
	Vector3();
	Vector3(float x, float y, float z);
	//Metoda obliczajaca dlugosc wektora.
	float length();
	//Przeladowane operatory.
	Vector3 &operator=(const Vector3 &);
	Vector3 operator/(float f);
	Vector3 &operator+=(const Vector3 &);
	//metoda statyczna obliczajaca iloczyn wektorowy.
	static Vector3 crossProduct(Vector3 v1, Vector3 v2);	
};

//Przeladowany operator odejmowania.
Vector3 operator-(Vector3 v1, Vector3 v2);

//Klasa odpowiadajaca za przechowanie wczytanego obiektu i narysowanie go.
class OpenGLClass : public CWnd
{
	public:
		//Timer.
		UINT_PTR timer;
		//Pozycja obiektu w plaszczynie okna.
		float xPosition;
		float yPosition;
		//Obrot obiektu.
		float xRotation;
		float yRotation;
		//Przyblizenie/oddalenie.
		float zoomScaling;
		//Skrajne punkty obiektu.
		float maxX;
		float minX;
		float maxY;
		float minY;
		float maxZ;
		float minZ;
		//Srodek bounding sphere.
		float centerX;
		float centerY;
		float centerZ;
		//Promien bounding sphere.
		float radius;
		//Lista vertexow.
		vector<Vertex> ver;
		//Lista polygonow.
		vector<vector<int>> faces;
		//Lista list zawierajacych normalne dla kazdego vertexu (normalne polygonow, do ktorych nalezy dany vertex).
		vector<vector<Vector3>> list;
		//Lista normalnych vertexow.
		vector<Vector3> vertexNormals;
		//Zmienna okreslajaca, czy wyswietlany jest poczatkowy obiekt.
		bool useDefault;

	private:
		CWnd  *hWnd;
		HDC   hdc;			
		HGLRC hrc;			

	public:
		//Konstruktor.
		OpenGLClass();

		//Stworzenie okna OpenGL.
		void createOpenGL(RECT rect, CWnd *parent);
		//Inicjalizacja OpenGL.
		void initializeOpenGL();
		//Rysowanie sceny.
		void drawScene();
		//Wczytanie obiektu z pliku *.obj.
		vector<Vertex> loadFromFile(char *path);
		//Ustawienie nowych punktow skrajnych.
		void setMinMax(float x, float y, float z);
		//Ustawienie bounding sphere.
		void setBoundingSphere();
		//Policzenie wektora normalnego dla polygonu.
		Vector3 calculateNormal(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3);
		//Policzenie wektorow normalnych dla wszystkich vertexow.
		void calculateVertexNormals();
		//Przygotowanie po wczytaniu pliku.
		void prepareLoadedFile();

		//Metody zdarzeniowe.
		afx_msg void OnPaint();
		afx_msg void OnSize(UINT nType, int cx, int cy);
		afx_msg	void OnDraw(CDC *pDC);
		afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
		afx_msg void OnTimer(UINT nIDEvent);

		DECLARE_MESSAGE_MAP()
};