diff --git a/MeshViewerQt/Header/MshFile.h b/MeshViewerQt/Header/MshFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bc59e5a970d6cca4944be028f422d898678a038
--- /dev/null
+++ b/MeshViewerQt/Header/MshFile.h
@@ -0,0 +1,75 @@
+#pragma once
+#include <fstream>
+#include <vector>
+#include <QMatrix4x4>
+
+enum ModelTyp {
+	null,
+	dynamicMesh,
+	cloth,
+	bone,
+	staticMesh,
+	shadowMesh = 6
+};
+
+struct BoundingBox {
+	float quaternion[4];
+	float center[3];
+	float extents[3];
+};
+
+struct ChunkHeader {
+	char name[5];
+	std::uint32_t size;
+	std::streampos position;
+};
+
+struct Segment {
+	std::uint32_t textureIndex	= 0;
+	float* vertex				= nullptr;
+	float* uv					= nullptr;
+	std::vector<std::vector<std::uint32_t>> polyIndices;	// indices into vertex array
+};
+
+struct Model {
+	std::string name			= "";
+	std::string parent			= "";
+	ModelTyp type				= null;
+	std::int32_t renderFlags	= -1;
+	QMatrix4x4 m4x4Translation;
+	std::vector<Segment*> segmList;
+};
+
+
+class MshFile
+{
+public:
+	MshFile(const char* path);
+	~MshFile();
+
+private:
+	std::vector<Model*>* m_vModels;
+	std::fstream m_fsMesh;
+	std::vector<std::string> m_vTextureNames;
+	BoundingBox m_sceneBbox;
+
+private:
+	void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t length);
+
+	void analyseMsh2Chunks(std::list<ChunkHeader*> &chunkList);
+
+	void analyseMatdChunks(std::list<ChunkHeader*> &chunkList);
+
+	void analyseModlChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
+	void analyseGeomChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
+	void analyseSegmChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
+	void analyseClthChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
+
+	void readVertex(Segment* dataDestination, std::streampos position);
+	void readUV(Segment* dataDestination, std::streampos position);
+
+public:
+	std::vector<Model*>* getModels() const;
+	std::vector<std::string> getTextureNames() const;
+	BoundingBox getBoundingBox() const;
+};
\ No newline at end of file
diff --git a/MeshViewerQt/Header/OpenGlViewer.h b/MeshViewerQt/Header/OpenGlViewer.h
index 00770763812ca9c30209a4b09090e588ab9b9b5a..d0b258927a80db67ef954e1a3c5638ea0098b5ca 100644
--- a/MeshViewerQt/Header/OpenGlViewer.h
+++ b/MeshViewerQt/Header/OpenGlViewer.h
@@ -1,10 +1,22 @@
 #pragma once
-
 #include <QOpenGLWidget>
 #include <QOpenGLFunctions>
 #include <QOpenGLBuffer>
 #include <QOPenGLVertexArrayObject>
 #include <QOpenGlShaderProgram>
+#include "..\Header\MshFile.h"
+
+struct Vertex {
+	GLfloat position[3];
+	GLfloat uv[2];
+};
+
+struct textureData {
+	bool alpha;
+	std::uint32_t width;
+	std::uint32_t height;
+	std::vector<std::uint8_t>* data;
+};
 
 class OpenGlViewer : public QOpenGLWidget, protected QOpenGLFunctions
 {
@@ -15,17 +27,37 @@ public:
 	~OpenGlViewer();
 
 private:
-	QOpenGLBuffer mVertexBuffer;
-	QOpenGLVertexArrayObject mVertexArray;
-	QOpenGLShaderProgram* mProgram = nullptr;
+// OpenGL ======================================
+	QOpenGLBuffer m_vertexBuffer;
+	QOpenGLVertexArrayObject m_vertexArray;
+	QOpenGLShaderProgram* m_program = nullptr;
 
-private:
-	void printContextInformation();
+// Data ========================================
+	std::vector<Model*>* m_vModels = nullptr;
+	std::vector<textureData*> m_vTextures;
+	BoundingBox m_sceneBoundings;
+
+// Transformation ==============================
+	float m_fRotX		= 0;
+	float m_fRotY		= 0;
+	float m_fRotZ		= 0;
+	float m_fTranX		= 0;
+	float m_fTranY		= 0;
+	float m_fTranZ		= 0;
+
+// Camera ======================================
+	float m_fFOV		= 45.0f;
+	float m_fMinView	= 0.1f;
+	float m_fMaxView	= 100.0f;
 
-protected:
+private:
 	virtual void initializeGL() override final;
 	virtual void resizeGL(int w, int h) override final;
 	virtual void paintGL() override final;
 
+	void printContextInformation();
+	void deleteData();
+
 public:
+	void setData(std::vector<Model*>* models, std::vector<textureData*> textures);
 };
diff --git a/MeshViewerQt/Header/Vertex.h b/MeshViewerQt/Header/Vertex.h
index d0fbdd01267c4544f4232342bef6a6786c5ecc77..d94717aad7766206c98f537bd717eea6029ce3dc 100644
--- a/MeshViewerQt/Header/Vertex.h
+++ b/MeshViewerQt/Header/Vertex.h
@@ -1,5 +1,4 @@
-#ifndef VERTEX_H
-#define VERTEX_H
+#pragma once
 
 #include <QVector3D>
 
@@ -51,5 +50,3 @@ void inline Vertex::setColor(const QVector3D& color) { m_color = color; }
 Q_DECL_CONSTEXPR inline int Vertex::positionOffset() { return offsetof(Vertex, m_position); }
 Q_DECL_CONSTEXPR inline int Vertex::colorOffset() { return offsetof(Vertex, m_color); }
 Q_DECL_CONSTEXPR inline int Vertex::stride() { return sizeof(Vertex); }
-
-#endif // VERTEX_H
\ No newline at end of file
diff --git a/MeshViewerQt/Header/defines.h b/MeshViewerQt/Header/defines.h
index 54034d43798fbfc56fa46594498b719f125d0202..cbf9149eebe332e3d467863849aa0a609b52e453 100644
--- a/MeshViewerQt/Header/defines.h
+++ b/MeshViewerQt/Header/defines.h
@@ -5,6 +5,4 @@
 #define WINDOW_HEIGHT				480
 
 #define DEFAULT_STATUS_MESSAGE		"Mesh Viewer pre alpha by Anakin"
-#define DEFAULT_MAJOR_VERSION		4
-#define DEFAULT_MINOR_VERSION		5
-#define DEAFAULT_BACKGROUND			0.5000f, 0.8000f, 1.0000f, 0.0000f
+
diff --git a/MeshViewerQt/Resources/MainWindow.qrc b/MeshViewerQt/Resources/MainWindow.qrc
index d3991903d109487bbd1f9c74a88397862f481819..3d2b5780c5a5c7c5f977ff273ef4d79899d6aa30 100644
--- a/MeshViewerQt/Resources/MainWindow.qrc
+++ b/MeshViewerQt/Resources/MainWindow.qrc
@@ -5,5 +5,7 @@
     <qresource prefix="/shaders">
         <file>simple.frag</file>
         <file>simple.vert</file>
+        <file>TextureShader.frag</file>
+        <file>TextureShader.vert</file>
     </qresource>
 </RCC>
diff --git a/MeshViewerQt/Resources/TextureShader.frag b/MeshViewerQt/Resources/TextureShader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..a3e33203ad8d7cef8baed75ccae3b024a9fdd24c
--- /dev/null
+++ b/MeshViewerQt/Resources/TextureShader.frag
@@ -0,0 +1,12 @@
+#version 450
+
+// Input
+in vec2 UV;
+
+// Output
+out vec4 color;
+
+void main()
+{
+	color = texture(textureSampler, UV).rgb;
+}
\ No newline at end of file
diff --git a/MeshViewerQt/Resources/TextureShader.vert b/MeshViewerQt/Resources/TextureShader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..f1c181efc24ad476433296ce656491458bc4a050
--- /dev/null
+++ b/MeshViewerQt/Resources/TextureShader.vert
@@ -0,0 +1,17 @@
+#version 450
+
+// Input vertex data, different for all executions of this shader
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec3 vertexUV;
+
+// Input that stay constant fpr the whole mesh
+uniform mat4 MVP;
+
+// Output
+out vec2 UV;
+
+void main()
+{
+	gl_Position = MVP * vec4(vertexPosition, 1);
+	UV = vertexUV;
+}
\ No newline at end of file
diff --git a/MeshViewerQt/Source/MainWindow.cpp b/MeshViewerQt/Source/MainWindow.cpp
index 969ce64fd0c8c81930b25d24ca8502bb508d4076..7a740cae435ecd0286334ba393aebc2004f065d7 100644
--- a/MeshViewerQt/Source/MainWindow.cpp
+++ b/MeshViewerQt/Source/MainWindow.cpp
@@ -1,6 +1,6 @@
-#include "MainWindow.h"
-#include "OpenGlViewer.h"
-#include "defines.h"
+#include "..\Header\MainWindow.h"
+#include "..\Header\OpenGlViewer.h"
+#include "..\Header\defines.h"
 #include <QKeyEvent>
 #include <QMessageBox>
 
diff --git a/MeshViewerQt/Source/MshFile.cpp b/MeshViewerQt/Source/MshFile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06a5110f6df027bfedc80a40d6464ed50063f1e9
--- /dev/null
+++ b/MeshViewerQt/Source/MshFile.cpp
@@ -0,0 +1,593 @@
+#include "..\Header\MshFile.h"
+#include <iostream>
+
+
+// helper function to save data from file to any variable type
+#define F2V(variableName) reinterpret_cast<char*>(&variableName)
+
+
+/////////////////////////////////////////////////////////////////////////
+// public constructor/destructor
+
+MshFile::MshFile(const char * path)
+	: m_vModels(new std::vector<Model*>)
+{
+	//open file
+	m_fsMesh.open(path, std::ios::in | std::ios::binary);
+
+	if (!m_fsMesh.is_open())
+		throw std::invalid_argument(std::string("file not found: ") += path);
+
+	// go to file size information
+	m_fsMesh.seekg(4);
+
+	std::uint32_t tmp_fileSize;
+	std::list<ChunkHeader*> tmp_mainChunks;
+
+	// get all chunks under HEDR
+	m_fsMesh.read(F2V(tmp_fileSize), sizeof(tmp_fileSize));
+	loadChunks(tmp_mainChunks, m_fsMesh.tellg(), tmp_fileSize);
+
+	// evaulate HEDR subchunks (= find MSH2)
+	for (ChunkHeader* it : tmp_mainChunks)
+	{
+		if (!strcmp("MSH2", it->name))
+		{
+			// get all subchunks
+			std::list<ChunkHeader*> tmp_msh2Chunks;
+			loadChunks(tmp_msh2Chunks, it->position, it->size);
+
+			// evaluate MSH2 subchunks
+			analyseMsh2Chunks(tmp_msh2Chunks);
+
+			// clean up
+			while (!tmp_msh2Chunks.empty())
+			{
+				ChunkHeader* curs = tmp_msh2Chunks.front();
+				tmp_msh2Chunks.pop_front();
+				delete curs;
+			}
+		}
+	}
+
+	// clean up
+	while (!tmp_mainChunks.empty())
+	{
+		ChunkHeader* cur = tmp_mainChunks.front();
+		tmp_mainChunks.pop_front();
+		delete cur;
+	}
+
+	// close file
+	m_fsMesh.close();
+}
+
+MshFile::~MshFile()
+{
+	m_vTextureNames.clear();
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+// private functions
+
+void MshFile::loadChunks(std::list<ChunkHeader*>& destination, std::streampos start, const std::uint32_t length)
+{
+	// jump to first chunk
+	m_fsMesh.seekg(start);
+
+	do
+	{
+		ChunkHeader* tmp_header = new ChunkHeader();
+
+		// get information
+		m_fsMesh.read(F2V(tmp_header->name[0]), sizeof(tmp_header->name) - 1);
+		m_fsMesh.read(F2V(tmp_header->size), sizeof(tmp_header->size));
+		tmp_header->position = m_fsMesh.tellg();
+
+		// store information
+		destination.push_back(tmp_header);
+
+		// jump to next header
+		m_fsMesh.seekg(tmp_header->size, std::ios_base::cur);
+
+		// out of file. Maybe a size information is corrupted
+		if (!m_fsMesh.good())
+		{
+			//TODO: different way for output
+			std::cout << "WARNING: corrupted file. Trying to continue" << std::endl;
+			m_fsMesh.clear();
+			break;
+		}
+
+	} while (m_fsMesh.tellg() - start != length);
+}
+
+void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
+{
+	for (auto& it : chunkList)
+	{
+		// scene information
+		if (!strcmp("SINF", it->name))
+		{
+			// get SINF subchunks
+			std::list<ChunkHeader*> tmp_sinfChunks;
+			loadChunks(tmp_sinfChunks, it->position, it->size);
+
+			// evaluate SINF subchunks
+			for (auto& it : tmp_sinfChunks)
+			{
+				if (!strcmp("BBOX", it->name))
+				{
+					m_fsMesh.seekg(it->position);
+
+					// read in the quaternion
+					for (int i = 0; i < 4; i++)
+						m_fsMesh.read(F2V(m_sceneBbox.quaternion[i]), sizeof(float));
+
+					//read in the center
+					for (int i = 0; i < 3; i++)
+						m_fsMesh.read(F2V(m_sceneBbox.center[i]), sizeof(float));
+
+					//read in the extents
+					for (int i = 0; i < 3; i++)
+						m_fsMesh.read(F2V(m_sceneBbox.extents[i]), sizeof(float));
+				}
+			}
+
+			// clean up SINF subchunks
+			for (ChunkHeader* it : tmp_sinfChunks)
+				delete it;
+		}
+
+		// material list
+		else if (!strcmp("MATL", it->name))
+		{
+			// "useless" information how many MATD follow, jump over it
+			m_fsMesh.seekg(it->position);
+			m_fsMesh.seekg(sizeof(std::uint32_t), std::ios_base::cur);
+
+			// get all MATL subchunk
+			std::list<ChunkHeader*> tmp_matlChunks;
+			loadChunks(tmp_matlChunks, m_fsMesh.tellg(), it->size - 4);
+
+			// evaluate MATL subchunks
+			for (auto& it : tmp_matlChunks)
+			{
+				// This shouldn't be anything else than MATD
+				if (!strcmp("MATD", it->name))
+				{
+					// get all subchunks from MATD
+					std::list<ChunkHeader*> tmp_matdChunks;
+					loadChunks(tmp_matdChunks, it->position, it->size);
+
+					m_vTextureNames.push_back("");
+
+					// analyse MATD subchunks
+					analyseMatdChunks(tmp_matdChunks);
+
+					// clean up MATD subchunks
+					while (!tmp_matdChunks.empty())
+					{
+						ChunkHeader* cur = tmp_matdChunks.front();
+						tmp_matdChunks.pop_front();
+						delete cur;
+					}
+				}
+			}
+
+			// clean up MATL subchunks
+			while (!tmp_matlChunks.empty())
+			{
+				ChunkHeader* cur = tmp_matlChunks.front();
+				tmp_matlChunks.pop_front();
+				delete cur;
+			}
+		}
+
+		// model
+		else if (!strcmp("MODL", it->name))
+		{
+			Model* new_model = new Model;
+
+			// get all MODL subchunks
+			std::list<ChunkHeader*> tmp_chunks;
+			loadChunks(tmp_chunks, it->position, it->size);
+
+			// evaluate MODL subchunks
+			analyseModlChunks(new_model, tmp_chunks);
+
+			//clean up MODL subchunks
+			while (!tmp_chunks.empty())
+			{
+				ChunkHeader* cur = tmp_chunks.front();
+				tmp_chunks.pop_front();
+				delete cur;
+			}
+
+			// save Model data
+			m_vModels->push_back(new_model);
+		}
+	}
+}
+
+void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
+{
+	for (auto& it : chunkList)
+	{
+		if (!strcmp("TX0D", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			char* buffer = new char[it->size + 1];
+			*buffer = { 0 };
+			m_fsMesh.read(buffer, it->size);
+			m_vTextureNames.back() = buffer;
+			delete[] buffer;
+		}
+	}
+}
+
+void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
+{
+	for (auto& it : chunkList)
+	{
+		// model type
+		if (!strcmp("MTYP", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			std::uint32_t tmp_type;
+			m_fsMesh.read(F2V(tmp_type), sizeof(tmp_type));
+			dataDestination->type = (ModelTyp)tmp_type;
+		}
+
+		// parent name
+		else if (!strcmp("PRNT", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			char* buffer = new char[it->size + 1];
+			*buffer = { 0 };
+			m_fsMesh.read(buffer, it->size);
+			dataDestination->parent = buffer;
+			delete[] buffer;
+		}
+
+		// model name
+		else if (!strcmp("NAME", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			char* buffer = new char[it->size + 1];
+			*buffer = { 0 };
+			m_fsMesh.read(buffer, it->size);
+			dataDestination->name = buffer;
+			delete[] buffer;
+		}
+
+		// render flags
+		else if (!strcmp("FLGS", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			m_fsMesh.read(F2V(dataDestination->renderFlags), sizeof(dataDestination->renderFlags));
+		}
+
+		// translation
+		else if (!strcmp("TRAN", it->name))
+		{
+			float tmp_scale[3];
+			float tmp_rotation[4];
+			float tmp_trans[3];
+
+			m_fsMesh.seekg(it->position);
+
+			// read in the data
+			for (int i = 0; i < 3; i++)
+				m_fsMesh.read(F2V(tmp_scale[i]), sizeof(float));
+
+			for (int i = 0; i < 4; i++)
+				m_fsMesh.read(F2V(tmp_rotation[i]), sizeof(float));
+
+			for (int i = 0; i < 3; i++)
+				m_fsMesh.read(F2V(tmp_trans[i]), sizeof(float));
+
+			// modify the matrix
+			dataDestination->m4x4Translation.scale(tmp_scale[0], tmp_scale[1], tmp_scale[2]);
+			dataDestination->m4x4Translation.rotate(QQuaternion(tmp_rotation[3], tmp_rotation[0], tmp_rotation[1], tmp_rotation[2]));
+			dataDestination->m4x4Translation.translate(tmp_trans[0], tmp_trans[1], tmp_trans[2]);
+
+		}
+
+		// geometry data
+		else if (!strcmp("GEOM", it->name))
+		{
+			// get all GEOM subchunks
+			std::list<ChunkHeader*> tmp_geomChunks;
+			loadChunks(tmp_geomChunks, it->position, it->size);
+
+			// evaluate GEOM subchunks
+			analyseGeomChunks(dataDestination, tmp_geomChunks);
+
+			// clean up GEOM subchunks
+			while (!tmp_geomChunks.empty())
+			{
+				ChunkHeader* cur = tmp_geomChunks.front();
+				tmp_geomChunks.pop_front();
+				delete cur;
+			}
+		}
+	}
+}
+
+void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
+{
+	for (auto& it : chunkList)
+	{
+		// segment
+		if (!strcmp("SEGM", it->name))
+		{
+			// get all SEGM subchunks
+			std::list<ChunkHeader*> tmp_segmChunks;
+			loadChunks(tmp_segmChunks, it->position, it->size);
+
+			// evaluate SEGM subchunks
+			analyseSegmChunks(dataDestination, tmp_segmChunks);
+
+			// clean up SEGM subchunk
+			while (!tmp_segmChunks.empty())
+			{
+				ChunkHeader* cur = tmp_segmChunks.front();
+				tmp_segmChunks.pop_front();
+				delete cur;
+			}
+		}
+
+		// cloth
+		else if (!strcmp("CLTH", it->name))
+		{
+			// get all CLTH subchunks
+			std::list<ChunkHeader*> tmp_clthChunks;
+			loadChunks(tmp_clthChunks, it->position, it->size);
+
+			// evaluate CLTH subchunks
+			analyseClthChunks(dataDestination, tmp_clthChunks);
+
+			// clean up CLTH subchunks
+			while (!tmp_clthChunks.empty())
+			{
+				ChunkHeader* cur = tmp_clthChunks.front();
+				tmp_clthChunks.pop_front();
+				delete cur;
+			}
+		}
+	}
+}
+
+void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
+{
+	Segment* new_segment = new Segment;
+
+	for (auto& it : chunkList)
+	{
+		// material index
+		if (!strcmp("MATI", it->name))
+		{
+			m_fsMesh.seekg(it->position);
+			m_fsMesh.read(F2V(new_segment->textureIndex), sizeof(new_segment->textureIndex));
+		}
+
+		// position list (vertex)
+		else if (!strcmp("POSL", it->name))
+		{
+			readVertex(new_segment, it->position);
+		}
+
+		// normals
+		/*else if (!strcmp("NRML", it->name))
+		{
+		fsMesh.seekg(it->position);
+		std::uint32_t tempSize;
+		fsMesh.read(reinterpret_cast<char*>(&tempSize), sizeof(tempSize));
+		// List of normals
+		// long int - 4 - number of normal vectores stored in this list
+		// float[3][] - 12 each - UVW vector for each vertex
+		}*/
+
+		// uv
+		else if (!strcmp("UV0L", it->name))
+		{
+			readUV(new_segment, it->position);
+		}
+
+		// polygons (indices into vertex/uv list)
+		else if (!strcmp("STRP", it->name))
+		{
+			// don't get null, bone, shadowMesh and hidden mesh indices
+			if (dataDestination->type == null ||
+				dataDestination->type == bone ||
+				dataDestination->type == shadowMesh ||
+				dataDestination->renderFlags == 1)
+				continue;
+
+			// jump to the data section and read the size;
+			std::uint32_t tmp_size;
+			m_fsMesh.seekg(it->position);
+			m_fsMesh.read(F2V(tmp_size), sizeof(tmp_size));
+
+			int highBitCount(0);
+			std::vector<uint32_t> new_poly;
+
+			for (unsigned int i = 0; i < tmp_size; i++)
+			{
+				// ReadData
+				std::uint16_t tmp_value;
+				m_fsMesh.read(F2V(tmp_value), sizeof(tmp_value));
+
+				// Check if highbit is set
+				if (tmp_value >> 15)
+				{
+					highBitCount++;
+					// remove the high bit, to get the actually value
+					tmp_value = (std::uint16_t(tmp_value << 1) >> 1);
+				}
+
+				// save data
+				new_poly.push_back((std::uint32_t)tmp_value);
+
+				// if the last 2 highBits are set, it was a new poly
+				if (highBitCount == 2)
+				{
+					// reset highBitCount
+					highBitCount = 0;
+
+					// remove the last two values..
+					std::uint32_t temp[2];
+					for (int i = 0; i < 2; i++)
+					{
+						temp[i] = new_poly.back();
+						new_poly.pop_back();
+					}
+
+					// ..save the old polygon..
+					new_segment->polyIndices.push_back(new_poly);
+
+					// ..and move the values to a new polygon
+					new_poly.clear();
+					for (int i = 1; i >= 0; i--)
+						new_poly.push_back(temp[i]);
+
+				}	// if high bit set
+
+			}	// for all values
+
+			// save the last polygon (no 2 high bit followed)
+			new_segment->polyIndices.push_back(new_poly);
+
+			// kick the first element, it's empty as a reason of the algo above;
+			new_segment->polyIndices.erase(new_segment->polyIndices.begin());
+		}
+	}
+
+	dataDestination->segmList.push_back(new_segment);
+}
+
+void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
+{
+	Segment* new_segment = new Segment;
+
+	for (auto& it : chunkList)
+	{
+		// texture name
+		if (!strcmp("CTEX", it->name))
+		{
+			// read the texture name
+			m_fsMesh.seekg(it->position);
+			char* buffer = new char[it->size + 1];
+			*buffer = { 0 };
+			m_fsMesh.read(buffer, it->size);
+
+			// search if it is already known
+			bool tmp_found(false);
+			for (unsigned int i = 0; i < m_vTextureNames.size(); i++)
+			{
+				if (!strcmp(buffer, m_vTextureNames[i].c_str()))
+				{
+					// if found, save the index and stop searching
+					new_segment->textureIndex = i;
+					tmp_found = true;
+					break;
+				}
+			}
+
+			// if it was not found add the texturename to the list
+			if (!tmp_found)
+			{
+				m_vTextureNames.push_back(std::string(buffer));
+				new_segment->textureIndex = m_vTextureNames.size() - 1;
+			}
+
+			delete[] buffer;
+		}
+
+		// position list (vertex)
+		else if (!strcmp("CPOS", it->name))
+		{
+			readVertex(new_segment, it->position);
+		}
+
+		// uv 
+		else if (!strcmp("CUV0", it->name))
+		{
+			readUV(new_segment, it->position);
+		}
+
+		// triangles (indices into vertex/uv list)
+		else if (!strcmp("CMSH", it->name))
+		{
+			// jump to the data section and read the size;
+			std::uint32_t tmp_size;
+			m_fsMesh.seekg(it->position);
+			m_fsMesh.read(F2V(tmp_size), sizeof(tmp_size));
+
+			std::vector<uint32_t> new_poly;
+
+			// for every triangle..
+			for (unsigned int i = 0; i < tmp_size * 3; i += 3)
+			{
+				new_poly.clear();
+
+				// ..get the 3 indices and save them
+				for (int j = 0; j < 3; j++)
+				{
+					std::uint32_t tmp_value;
+					m_fsMesh.read(F2V(tmp_value), sizeof(std::uint32_t));
+					new_poly.push_back(tmp_value);
+				}
+
+				new_segment->polyIndices.push_back(new_poly);
+			}
+		}
+	}
+
+	dataDestination->segmList.push_back(new_segment);
+}
+
+void MshFile::readVertex(Segment * dataDestination, std::streampos position)
+{
+	std::uint32_t tmp_size;
+	m_fsMesh.seekg(position);
+	m_fsMesh.read(F2V(tmp_size), sizeof(tmp_size));
+
+	dataDestination->vertex = new float[tmp_size * 3];
+
+	for (unsigned int i = 0; i < tmp_size * 3; i++)
+		m_fsMesh.read(F2V(dataDestination->vertex[i]), sizeof(float));
+}
+
+void MshFile::readUV(Segment * dataDestination, std::streampos position)
+{
+	std::uint32_t tmp_size;
+	m_fsMesh.seekg(position);
+	m_fsMesh.read(F2V(tmp_size), sizeof(tmp_size));
+
+	dataDestination->uv = new float[tmp_size * 2];
+
+	for (unsigned int i = 0; i < tmp_size * 2; i++)
+		m_fsMesh.read(F2V(dataDestination->uv[i]), sizeof(float));
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+// public getter
+
+std::vector<Model*>* MshFile::getModels() const
+{
+	return m_vModels;
+}
+
+std::vector<std::string> MshFile::getTextureNames() const
+{
+	return m_vTextureNames;
+}
+
+BoundingBox MshFile::getBoundingBox() const
+{
+	return m_sceneBbox;
+}
diff --git a/MeshViewerQt/Source/OpenGlViewer.cpp b/MeshViewerQt/Source/OpenGlViewer.cpp
index 292c76d3a954613e5172ddaa5d9c8ffcabf465f3..d147ea058ad3deec3b640f4ce696c18258df9986 100644
--- a/MeshViewerQt/Source/OpenGlViewer.cpp
+++ b/MeshViewerQt/Source/OpenGlViewer.cpp
@@ -1,14 +1,32 @@
-#include "OpenGlViewer.h"
-#include "defines.h"
-#include "Vertex.h"
-
+#include "..\Header\OpenGlViewer.h"
+#include "..\Header\defines.h"
 #include <iostream>
 
-static const Vertex sg_vertexes[] = {
-	Vertex(QVector3D(0.00f,  0.75f, 1.0f), QVector3D(1.0f, 0.0f, 0.0f)),
-	Vertex(QVector3D(0.75f, -0.75f, 1.0f), QVector3D(0.0f, 1.0f, 0.0f)),
-	Vertex(QVector3D(-0.75f, -0.75f, 1.0f), QVector3D(0.0f, 0.0f, 1.0f))
-};
+
+/////////////////////////////////////////////////////////////////////////
+// Defined values
+
+//opengl
+#define DEFAULT_MAJOR_VERSION		4
+#define DEFAULT_MINOR_VERSION		5
+#define DEAFAULT_BACKGROUND			0.5000f, 0.8000f, 1.0000f, 0.0000f
+
+//piplines
+#define VERTEX_INDEX_XYZ		0
+#define VERTEX_INDEX_UV			1
+
+#define VERTEX_COMPONENTS_XYZ	3
+#define VERTEX_COMPONENTS_UV	2
+
+#define VERTEX_SIZE_XYZ			(sizeof(float) * VERTEX_COMPONENTS_XYZ)
+#define VERTEX_SIZE_UV			(sizeof(float) * VERTEX_COMPONENTS_UV)
+
+#define VERTEX_OFFSET_XYZ		0
+#define VERTEX_OFFSET_UV		(VERTEX_SIZE_XYZ)
+
+
+/////////////////////////////////////////////////////////////////////////
+// public constructor/destructor
 
 OpenGlViewer::OpenGlViewer(QWidget *parent)
 	: QOpenGLWidget(parent)
@@ -23,9 +41,63 @@ OpenGlViewer::OpenGlViewer(QWidget *parent)
 
 OpenGlViewer::~OpenGlViewer()
 {
-	mVertexArray.destroy();
-	mVertexBuffer.destroy();
-	delete mProgram;
+	m_vertexArray.destroy();
+	m_vertexBuffer.destroy();
+	delete m_program;
+
+	deleteData();
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+// private functions
+
+void OpenGlViewer::initializeGL()
+{
+	initializeOpenGLFunctions();
+	printContextInformation();
+
+	//glEnable(GL_DEPTH_TEST);
+	glClearColor(DEAFAULT_BACKGROUND);
+
+	m_program = new QOpenGLShaderProgram();
+	m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert");
+	m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/simple.frag");
+	m_program->link();
+	m_program->bind();
+
+	m_vertexBuffer.create();
+	m_vertexBuffer.bind();
+	m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
+
+	m_vertexArray.create();
+	m_vertexArray.bind();
+	m_program->enableAttributeArray(0);
+	m_program->enableAttributeArray(1);
+	//m_program->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());
+	//m_program->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());
+
+	m_vertexArray.release();
+	m_vertexBuffer.release();
+	m_program->release();
+
+}
+
+void OpenGlViewer::resizeGL(int w, int h)
+{
+	//TODO: change perspective
+}
+
+void OpenGlViewer::paintGL()
+{
+	//TODO: paint here
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	m_program->bind();
+	m_vertexArray.bind();
+	//glDrawArrays(GL_TRIANGLES, 0, sizeof(sg_vertexes) / sizeof(sg_vertexes[0]));
+	m_vertexArray.release();
+	m_program->release();
 }
 
 void OpenGlViewer::printContextInformation()
@@ -49,52 +121,69 @@ void OpenGlViewer::printContextInformation()
 	std::cout << glType.toStdString() << " - " << glVersion.toStdString() << " (" << glProfile.toStdString() << ")";
 }
 
-void OpenGlViewer::initializeGL()
+void OpenGlViewer::deleteData()
 {
-	initializeOpenGLFunctions();
-	printContextInformation();
-
-	//glEnable(GL_DEPTH_TEST);
-	glClearColor(DEAFAULT_BACKGROUND);
-
-	mProgram = new QOpenGLShaderProgram();
-	mProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert");
-	mProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/simple.frag");
-	mProgram->link();
-	mProgram->bind();
+	if (m_vModels != NULL)
+	{
+		while (!m_vModels->empty())
+		{
+			// remove the last Model
+			Model* modelVectorElement = m_vModels->back();
+			m_vModels->pop_back();
+
+			while (!modelVectorElement->segmList.empty())
+			{
+				// remove the last Segment
+				Segment* segmentVectorElement = modelVectorElement->segmList.back();
+				modelVectorElement->segmList.pop_back();
+
+				// delete data from Segment
+				delete[] segmentVectorElement->uv;
+				delete[] segmentVectorElement->vertex;
+
+				while (!segmentVectorElement->polyIndices.empty())
+				{
+					// clear the poly vector and remove it from the list
+					segmentVectorElement->polyIndices.back().clear();
+					segmentVectorElement->polyIndices.pop_back();
+				}
+
+				// delete the actual Segment
+				delete segmentVectorElement;
+			}
+
+			// delete the actual Model
+			delete modelVectorElement;
+		}
+
+		// delete the Model's Vector
+		delete m_vModels;
+	}
 
-	mVertexBuffer.create();
-	mVertexBuffer.bind();
-	mVertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
-	mVertexBuffer.allocate(sg_vertexes, sizeof(sg_vertexes));
+	while (!m_vTextures.empty())
+	{
+		// remove the last texture
+		textureData* cursor = m_vTextures.back();
+		m_vTextures.pop_back();
 
-	mVertexArray.create();
-	mVertexArray.bind();
-	mProgram->enableAttributeArray(0);
-	mProgram->enableAttributeArray(1);
-	mProgram->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());
-	mProgram->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());
+		// delete the texture's data
+		cursor->data->clear();
 
-	mVertexArray.release();
-	mVertexBuffer.release();
-	mProgram->release();
+		//delete the texture's data vector
+		delete cursor->data;
 
+		//delete the texture
+		delete cursor;
+	}
 }
 
-void OpenGlViewer::resizeGL(int w, int h)
-{
-	//TODO: change perspective
-}
 
-void OpenGlViewer::paintGL()
-{
-	//TODO: paint here
-	glClear(GL_COLOR_BUFFER_BIT);
+/////////////////////////////////////////////////////////////////////////
+// public functions
 
-	mProgram->bind();
-	mVertexArray.bind();
-	glDrawArrays(GL_TRIANGLES, 0, sizeof(sg_vertexes) / sizeof(sg_vertexes[0]));
-	mVertexArray.release();
-	mProgram->release();
+void OpenGlViewer::setData(std::vector<Model*>* models, std::vector<textureData*> textures)
+{
+	m_vModels = models;
+	m_vTextures = textures;
 }
 
diff --git a/MeshViewerQt/main.cpp b/MeshViewerQt/main.cpp
index 4a9f64c2d85a1e62eacc58245d782c157ce6bd0d..8e6ee6cb6d5cd500065f4454ad0b2fbfa5098378 100644
--- a/MeshViewerQt/main.cpp
+++ b/MeshViewerQt/main.cpp
@@ -1,4 +1,4 @@
-#include "MainWindow.h"
+#include "Header\MainWindow.h"
 #include <QtWidgets/QApplication>
 
 int startGUI(int argc, char* argv[])