diff --git a/MeshViewerQt/Header/FileInterface.h b/MeshViewerQt/Header/FileInterface.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcc2f1533e03af27f92d3371031a1d34b98c6a68
--- /dev/null
+++ b/MeshViewerQt/Header/FileInterface.h
@@ -0,0 +1,72 @@
+#pragma once
+#include <fstream>
+#include <vector>
+#include <QMatrix4x4>
+
+//TODO: shouldn't be here
+enum ModelTyp {
+	null,
+	dynamicMesh,
+	cloth,
+	bone,
+	staticMesh,
+	shadowMesh = 6
+};
+
+struct BoundingBox {
+	float quaternion[4];
+	float center[3];
+	float extents[3];
+};
+
+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;	//TODO: should be removed
+	std::int32_t renderFlags	= -1;	//TODO: should be removed
+	QMatrix4x4 m4x4Translation;
+	std::vector<Segment*> segmList;
+};
+
+class FileInterface
+{
+public:
+	FileInterface(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);
+	};
+
+	virtual ~FileInterface()
+	{
+		// close file
+		m_fsMesh.close(); 
+
+		//clean up
+		m_vTextureNames.clear();
+	};
+
+protected:
+	std::vector<Model*>* m_vModels;
+	std::fstream m_fsMesh;
+	std::vector<std::string> m_vTextureNames;
+	BoundingBox m_sceneBbox;
+
+	virtual void import() = 0;
+
+public:
+	virtual std::vector<Model*>* getModels() const { return m_vModels; };
+	virtual std::vector<std::string> getTextureNames() const { return m_vTextureNames; };
+	virtual BoundingBox getBoundingBox() const { return m_sceneBbox; };
+};
\ No newline at end of file
diff --git a/MeshViewerQt/Header/MainWindow.h b/MeshViewerQt/Header/MainWindow.h
index 2d0a1310c0796ab6a069d93ed352ff14c38b1296..ca011cdc1754deb09cc15c433981e4a22c90c78d 100644
--- a/MeshViewerQt/Header/MainWindow.h
+++ b/MeshViewerQt/Header/MainWindow.h
@@ -18,6 +18,7 @@ private:
 // Functions
 private:
 	void setupWindow();
+	void import(const char* path);
 
 // Slots
 private slots:
diff --git a/MeshViewerQt/Header/MshFile.h b/MeshViewerQt/Header/MshFile.h
index 1bc59e5a970d6cca4944be028f422d898678a038..4fdf953816404f18e2baa6b513ecfad7ccb3573e 100644
--- a/MeshViewerQt/Header/MshFile.h
+++ b/MeshViewerQt/Header/MshFile.h
@@ -1,22 +1,6 @@
 #pragma once
-#include <fstream>
-#include <vector>
-#include <QMatrix4x4>
+#include "FileInterface.h"
 
-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];
@@ -24,36 +8,16 @@ struct ChunkHeader {
 	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
+class MshFile : public FileInterface
 {
 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;
+	virtual void import() override final;
 
-private:
 	void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t length);
 
 	void analyseMsh2Chunks(std::list<ChunkHeader*> &chunkList);
@@ -67,9 +31,4 @@ private:
 
 	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 b7ccc447d50b44f41e36a0f2f61d2f9e1b12ea6d..fe260b5827ef9a81d6e0df31d8b646a5926dae49 100644
--- a/MeshViewerQt/Header/OpenGlViewer.h
+++ b/MeshViewerQt/Header/OpenGlViewer.h
@@ -6,7 +6,7 @@
 #include <QOpenGlShaderProgram>
 #include <QOpenGlTexture>
 #include <QImage>
-#include "..\Header\MshFile.h"
+#include "..\Header\FileInterface.h"
 
 struct Vertex {
 	GLfloat position[3];
@@ -30,8 +30,8 @@ private:
 	QOpenGLShaderProgram* m_program = nullptr;
 
 // Data ========================================
-	std::vector<Model*>* m_vModels = nullptr;
-	std::vector<QImage*> m_vTextures;
+	std::vector<Model*>* m_vModels		= nullptr;
+	std::vector<QImage*>* m_vTextures	= nullptr;
 	BoundingBox m_sceneBoundings;
 
 // Transformation ==============================
@@ -49,13 +49,13 @@ private:
 
 private:
 	virtual void initializeGL() override final;
-	virtual void resizeGL(int w, int h) override final;
 	virtual void paintGL() override final;
 
 	void printContextInformation();
+	QMatrix4x4 getModelMatrix(unsigned int index) const;
 	QMatrix4x4 getMVPMatrix(unsigned int index) const;
 	void deleteData();
 
 public:
-	void setData(std::vector<Model*>* models, std::vector<QImage*> textures);
+	void setData(std::vector<Model*>* models, std::vector<QImage*>* textures, BoundingBox bbox);
 };
diff --git a/MeshViewerQt/Source/MainWindow.cpp b/MeshViewerQt/Source/MainWindow.cpp
index 7a740cae435ecd0286334ba393aebc2004f065d7..2c9b2051bd62da24e4dc97001246023398b5c7b1 100644
--- a/MeshViewerQt/Source/MainWindow.cpp
+++ b/MeshViewerQt/Source/MainWindow.cpp
@@ -1,8 +1,10 @@
 #include "..\Header\MainWindow.h"
 #include "..\Header\OpenGlViewer.h"
+#include "..\Header\MshFile.h"
 #include "..\Header\defines.h"
 #include <QKeyEvent>
 #include <QMessageBox>
+#include <QFileDialog>
 
 
 /////////////////////////////////////////////////////////////////////////
@@ -34,18 +36,85 @@ void MainWindow::setupWindow()
 
 	this->setCentralWidget(new OpenGlViewer(this));
 
+	ui->mainToolBar->addAction("Open File", this, &MainWindow::openFile);
 	ui->mainToolBar->addAction("File Info", this, &MainWindow::aboutFile);
 
 	ui->statusBar->showMessage(DEFAULT_STATUS_MESSAGE);
 }
 
+void MainWindow::import(const char * path)
+{
+	try
+	{
+		MshFile file(path);
+
+		// Models
+		std::vector<Model*>* tmp_models = file.getModels();
+
+		// Textures
+		std::vector<std::string> tmp_texNames = file.getTextureNames();
+		std::vector<QImage*>* tmp_textures = new std::vector<QImage*>;
+
+		std::string tmp_path = path;
+
+		while (tmp_path.back() != '/' && tmp_path.back() != '\\')
+			tmp_path.pop_back();
+
+		for (auto& it : tmp_texNames)
+		{
+			QImage* tmp_image = new QImage;
+
+			std::string test = tmp_path + it;
+			QString test2 = "D:\\workspaces\\Visual Studio 2015\\Projects\\OpenGL\\Release\\Msh\\texture32R.tga";
+
+			if (tmp_image->load(test2))
+				tmp_textures->push_back(tmp_image);
+			else
+			{
+				delete tmp_image;
+				tmp_image = new QImage(1, 1, QImage::Format_RGB32);
+				tmp_image->fill(Qt::red);
+				tmp_textures->push_back(tmp_image);
+			}
+		}
+
+		// add a solid default color at the end (maybe there is an invalid index later)
+		QImage* tmp_image = new QImage(1, 1, QImage::Format_RGB16);
+		tmp_image->fill(Qt::red);
+		tmp_textures->push_back(tmp_image);
+
+		tmp_texNames.clear();
+
+		// Bounding Box
+		BoundingBox tmp_bbox = file.getBoundingBox();
+
+		OpenGlViewer* tmp_viewer = dynamic_cast<OpenGlViewer*>(centralWidget());
+
+		tmp_viewer->setData(tmp_models, tmp_textures, tmp_bbox);
+
+	}
+	catch (std::invalid_argument e)
+	{
+		//TODO:
+		QMessageBox msg(this);
+		msg.addButton(QMessageBox::Ok);
+		msg.setText(QString::fromStdString(e.what()));
+		msg.setIcon(QMessageBox::Critical);
+		msg.setWindowTitle("Open File Error");
+
+		msg.exec();
+	}
+}
+
 
 /////////////////////////////////////////////////////////////////////////
 // private slots
 
 void MainWindow::openFile()
 {
-	//TODO: Open file
+	QString fileName = QFileDialog::getOpenFileName(this, "Open File", "../Release/Msh", "Mesh (*.msh)");
+
+	import(fileName.toStdString().c_str());
 }
 
 void MainWindow::aboutFile()
diff --git a/MeshViewerQt/Source/MshFile.cpp b/MeshViewerQt/Source/MshFile.cpp
index 06a5110f6df027bfedc80a40d6464ed50063f1e9..a683cc5e5f442079a897ccf06b4d88c966664375 100644
--- a/MeshViewerQt/Source/MshFile.cpp
+++ b/MeshViewerQt/Source/MshFile.cpp
@@ -10,14 +10,21 @@
 // public constructor/destructor
 
 MshFile::MshFile(const char * path)
-	: m_vModels(new std::vector<Model*>)
+	: FileInterface(path)
 {
-	//open file
-	m_fsMesh.open(path, std::ios::in | std::ios::binary);
+	import();
+}
+
+MshFile::~MshFile()
+{
+}
+
 
-	if (!m_fsMesh.is_open())
-		throw std::invalid_argument(std::string("file not found: ") += path);
+/////////////////////////////////////////////////////////////////////////
+// private functions
 
+void MshFile::import()
+{
 	// go to file size information
 	m_fsMesh.seekg(4);
 
@@ -57,20 +64,8 @@ MshFile::MshFile(const char * path)
 		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
@@ -572,22 +567,3 @@ void MshFile::readUV(Segment * dataDestination, std::streampos position)
 	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 73f4f1251532d5478b1813259a937a752214c64c..96fb28a8c224c836624adbda86e96730f0b88394 100644
--- a/MeshViewerQt/Source/OpenGlViewer.cpp
+++ b/MeshViewerQt/Source/OpenGlViewer.cpp
@@ -1,5 +1,7 @@
 #include "..\Header\OpenGlViewer.h"
+#include <cmath>
 #include <iostream>
+#include <QMessageBox>
 
 
 /////////////////////////////////////////////////////////////////////////
@@ -104,11 +106,6 @@ void OpenGlViewer::initializeGL()
 
 }
 
-void OpenGlViewer::resizeGL(int w, int h)
-{
-	//TODO: change perspective
-}
-
 void OpenGlViewer::paintGL()
 {
 	//TODO: paint here
@@ -134,8 +131,8 @@ void OpenGlViewer::paintGL()
 			for (auto& segmentIterator : m_vModels->at(modelIndex)->segmList)
 			{
 				// set the texture
-				std::uint32_t tmp_textureIndex = segmentIterator->textureIndex >= m_vTextures.size() ? m_vTextures.size() - 1 : segmentIterator->textureIndex;
-				m_oglTexture->setData(*m_vTextures.at(tmp_textureIndex));
+				std::uint32_t tmp_textureIndex = segmentIterator->textureIndex >= m_vTextures->size() ? m_vTextures->size() - 1 : segmentIterator->textureIndex;
+				m_oglTexture->setData(*m_vTextures->at(tmp_textureIndex));
 
 				// give the MVP to the shader
 				m_program->setUniformValue(m_uniformMVP, getMVPMatrix(modelIndex));
@@ -152,7 +149,7 @@ void OpenGlViewer::paintGL()
 			}
 		}
 	}
-	//glDrawArrays(GL_TRIANGLES, 0, sizeof(sg_vertexes) / sizeof(sg_vertexes[0]));
+
 	m_oglTexture->release();
 	m_vertexArray.release();
 	m_program->release();
@@ -179,14 +176,50 @@ void OpenGlViewer::printContextInformation()
 	std::cout << glType.toStdString() << " - " << glVersion.toStdString() << " (" << glProfile.toStdString() << ")";
 }
 
+QMatrix4x4 OpenGlViewer::getModelMatrix(unsigned int index) const
+{
+	QMatrix4x4 tmp_parent;
+
+	for (unsigned int loop = 0; loop < m_vModels->size(); loop++)
+	{
+		if (!strcmp(m_vModels->at(index)->parent.c_str(), m_vModels->at(loop)->name.c_str()))
+		{
+			tmp_parent = getModelMatrix(loop);
+			break;
+		}
+	}
+
+	return tmp_parent * m_vModels->at(index)->m4x4Translation;
+}
+
 QMatrix4x4 OpenGlViewer::getMVPMatrix(unsigned int index) const
 {
-	return QMatrix4x4();
+	QMatrix4x4 tmp_mvp;
+	
+	// projection
+	tmp_mvp.perspective(m_fFOV, float(QWidget::width()) / float(QWidget::height()), m_fMinView, m_fMaxView);
+	
+	// view
+	tmp_mvp.lookAt(QVector3D(m_fTranX, m_fTranY, m_fTranZ), QVector3D(m_fTranX, m_fTranY, m_fTranZ - 1), QVector3D(0, 0, 1));
+	
+	// user controlled rotation
+	tmp_mvp.rotate(m_fRotX, QVector3D(1, 0, 0));
+	tmp_mvp.rotate(m_fRotY, QVector3D(0, 1, 0));
+	tmp_mvp.rotate(m_fRotZ, QVector3D(0, 0, 1));
+
+	//scale to 1
+	float maxExtent = std::max(std::max(m_sceneBoundings.extents[0], m_sceneBoundings.extents[1]), m_sceneBoundings.extents[2]);
+	tmp_mvp.scale(1 / maxExtent); 
+
+	// move to center
+	tmp_mvp.translate(-m_sceneBoundings.center[0], -m_sceneBoundings.center[1], -m_sceneBoundings.center[2]);
+
+	return tmp_mvp * getModelMatrix(index);
 }
 
 void OpenGlViewer::deleteData()
 {
-	if (m_vModels != NULL)
+	if (m_vModels != nullptr)
 	{
 		while (!m_vModels->empty())
 		{
@@ -223,17 +256,19 @@ void OpenGlViewer::deleteData()
 		delete m_vModels;
 	}
 
-	while (!m_vTextures.empty())
+	if (m_vTextures != nullptr)
 	{
-		// remove the last texture
-		QImage* cursor = m_vTextures.back();
-		m_vTextures.pop_back();
-
-		//delete image
-		delete cursor;
+		while (!m_vTextures->empty())
+		{
+			// remove the last texture
+			QImage* cursor = m_vTextures->back();
+			m_vTextures->pop_back();
 
-		//delete the texture
-		delete cursor;
+			//delete image
+			delete cursor;
+		}
+		// delete the Textrue's Vector
+		delete m_vTextures;
 	}
 }
 
@@ -241,9 +276,73 @@ void OpenGlViewer::deleteData()
 /////////////////////////////////////////////////////////////////////////
 // public functions
 
-void OpenGlViewer::setData(std::vector<Model*>* models, std::vector<QImage*> textures)
+void OpenGlViewer::setData(std::vector<Model*>* models, std::vector<QImage*>* textures, BoundingBox bbox)
 {
+	// new Data, so clean up the old things
+	deleteData();
+
+	// save the variables
 	m_vModels = models;
 	m_vTextures = textures;
-}
+	m_sceneBoundings = bbox;
+
+	// collect vertex data of all models
+	std::vector<Vertex> tmp_bufferData;
+
+	for (auto& modIt : *m_vModels)		// for every model chunk
+	{
+		for (auto& segIt : modIt->segmList)		// for every cluster
+		{
+			for (auto& mshIt : segIt->polyIndices)		// for every polygon
+			{
+				if (mshIt.size() >= 3)		// multipoly
+				{
+					// for every triangle of the multi polygon
+					for (unsigned int tri = 0; tri < mshIt.size() - 2; tri++)
+					{
+						// for every edge of the triangle
+						for (int triEdge = 0; triEdge < 3; triEdge++)
+						{
+							Vertex tempVertex;
+							// every edge has 3 coordinates
+							for (int j = 0; j < 3; j++)
+								tempVertex.position[j] = (GLfloat)segIt->vertex[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 3 + j];
+
+							// and 2 UV
+							if (segIt->uv == NULL)
+							{
+								tempVertex.uv[0] = 1.0;
+								tempVertex.uv[1] = 1.0;
+							}
+							else
+							{
+								for (int j = 0; j < 2; j++)
+									tempVertex.uv[j] = (GLfloat)segIt->uv[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 2 + j];
+							}
+							tmp_bufferData.push_back(tempVertex);
+						}
+					}
+				}
+				else	// this shouldn't happen (polygon with less then 3 vertex)
+				{
+					deleteData();
+
+					QMessageBox msg(this);
+					msg.addButton(QMessageBox::Ok);
+					msg.setText("You have polygons with less then 3 vertices!");
+					msg.setIcon(QMessageBox::Critical);
+					msg.setWindowTitle("Open File Error");
+					msg.exec();
+					return;
+				}
+			}
+		}
+	}
+
 
+	m_vertexBuffer.bind();
+	m_vertexBuffer.allocate(tmp_bufferData.data(), sizeof(Vertex) * tmp_bufferData.size());
+	m_vertexBuffer.release();
+
+	tmp_bufferData.clear();
+}