diff --git a/src/Engine/Asset.cpp b/src/Engine/Asset.cpp
index 71458652f5638e4f1aa2430e2e5ac02310b42769..a7eae7646efc45e623d607bea21b3470986689ce 100644
--- a/src/Engine/Asset.cpp
+++ b/src/Engine/Asset.cpp
@@ -5,6 +5,7 @@
 #include <cassert>
 #include <map>
 #include <type_traits>
+#include <iostream>
 
 #include "fx/gltf.h"
 
@@ -15,8 +16,8 @@
 
 struct AssetInfo
 {
-	std::string name;
-	std::string relativePath;
+	std::string_view name;
+	std::string_view relativePath;
 };
 
 static const std::map<Asset::Sprite, AssetInfo> textureInfos
@@ -27,12 +28,12 @@ static const std::map<Asset::Sprite, AssetInfo> textureInfos
 	{ Asset::Sprite::Circle, {"Circle", "circle.png"} },
 };
 
-static const std::map<Asset::Mesh, AssetInfo> meshInfos
+static const std::map<size_t, AssetInfo> meshInfos
 {
-	{ Asset::Mesh::None, {"None", ""} },
-	{ Asset::Mesh::Cube, {"Cube", "Cube/Cube.gltf"} },
-	{ Asset::Mesh::SpritePlane, {"SpritePlane", "SpritePlane/SpritePlane.gltf"} },
-	{ Asset::Mesh::Helmet, {"Helmet", "Helmet/Helmet.gltf"} },
+	{ size_t(Asset::Mesh::None), {"None", ""} },
+	{ size_t(Asset::Mesh::Cube), {"Cube", "Cube/Cube.gltf"} },
+	{ size_t(Asset::Mesh::SpritePlane), {"SpritePlane", "SpritePlane/SpritePlane.gltf"} },
+	{ size_t(Asset::Mesh::Helmet), {"Helmet", "Helmet/Helmet.gltf"} },
 };
 
 bool Asset::CheckValid(Sprite sprite)
@@ -41,118 +42,112 @@ bool Asset::CheckValid(Sprite sprite)
 	return (0 <= static_cast<Type>(sprite) && static_cast<Type>(sprite) < static_cast<Type>(Sprite::COUNT)) || sprite == Sprite::None;
 }
 
-std::string Asset::GetPath(Sprite texture)
+std::string Asset::GetMeshPath(size_t i)
 {
-	assert(CheckValid(texture));
-	auto iterator = textureInfos.find(texture);
-	assert(iterator != textureInfos.end());
-	return static_cast<std::string>(textureFolderPath) + iterator->second.relativePath;
+	auto iterator = meshInfos.find(i);
+	if (iterator == meshInfos.end())
+		return {};
+	else
+		return std::string(meshFolderPath) + std::string(iterator->second.relativePath);
 }
 
-std::string Asset::GetName(Sprite texture)
+std::optional<Asset::MeshDocument> Asset::LoadMeshDocument(std::string_view path)
 {
-	assert(CheckValid(texture));
-	auto iterator = textureInfos.find(texture);
-	assert(iterator != textureInfos.end());
-	return iterator->second.name;
-}
-
-bool Asset::CheckValid(Mesh mesh)
-{
-	using Type = std::underlying_type_t<Mesh>;
-	return (0 <= static_cast<Type>(mesh) && static_cast<Type>(mesh) < static_cast<Type>(Mesh::COUNT)) || mesh == Mesh::None;
-}
-
-std::string Asset::GetPath(Mesh mesh)
-{
-	assert(CheckValid(mesh));
-	auto iterator = meshInfos.find(mesh);
-	assert(iterator != meshInfos.end());
-	return static_cast<std::string>(meshFolderPath) + iterator->second.relativePath;
-}
-
-std::string Asset::GetName(Mesh mesh)
-{
-	assert(CheckValid(mesh));
-	auto iterator = meshInfos.find(mesh);
-	assert(iterator != meshInfos.end());
-	return iterator->second.name;
-}
-
-Asset::MeshDocument Asset::LoadMeshDocument(Mesh mesh)
-{
-	const auto& path = GetPath(mesh);
-	return LoadMeshDocument(path);
+	try
+	{
+		const auto gltfDocument = fx::gltf::LoadFromText(std::string(path));
+
+		auto& primitive = gltfDocument.meshes[0].primitives[0];
+
+		auto posAccIterator = primitive.attributes.find("POSITION");
+		if (posAccIterator == primitive.attributes.end())
+		{
+			std::cerr << "Error. Found no position attribute for mesh." << std::endl;
+			return {};
+		}
+		auto& posAcc = gltfDocument.accessors[posAccIterator->second];
+		bool validAccessor = posAcc.type == fx::gltf::Accessor::Type::Vec3 && posAcc.componentType == fx::gltf::Accessor::ComponentType::Float;
+		if (!validAccessor)
+		{
+			std::cerr << "Error. Position attribute of mesh is in wrong format." << std::endl;
+			return {};
+		}
+		auto& posBufferView = gltfDocument.bufferViews[posAcc.bufferView];
+		const auto posByteOffset = posAcc.byteOffset + posBufferView.byteOffset;
+		
+
+		auto& uvAccessor = gltfDocument.accessors[primitive.attributes.find("TEXCOORD_0")->second];
+		assert(uvAccessor.type == fx::gltf::Accessor::Type::Vec2 && uvAccessor.componentType == fx::gltf::Accessor::ComponentType::Float);
+		auto& uvBufferView = gltfDocument.bufferViews[uvAccessor.bufferView];
+
+		
+
+		auto& normalAccessor = gltfDocument.accessors[primitive.attributes.find("NORMAL")->second];
+		assert(normalAccessor.type == fx::gltf::Accessor::Type::Vec3 && normalAccessor.componentType == fx::gltf::Accessor::ComponentType::Float);
+		auto& normalBufferView = gltfDocument.bufferViews[normalAccessor.bufferView];
+		
+
+		assert(posAcc.count == uvAccessor.count && posAcc.count == normalAccessor.count);
+
+		auto& indexAccessor = gltfDocument.accessors[primitive.indices];
+		assert(indexAccessor.type == fx::gltf::Accessor::Type::Scalar);
+		assert(indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort
+			|| indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedInt);
+		auto& indexBufferView = gltfDocument.bufferViews[indexAccessor.bufferView];
+
+		
+		MeshDocument::CreateInfo createInfo{};
+		createInfo.byteArray = std::move(gltfDocument.buffers[posBufferView.buffer].data);
+		createInfo.vertexCount = posAcc.count;
+		createInfo.posByteOffset = posByteOffset;
+		createInfo.uvByteOffset = uvBufferView.byteOffset + uvAccessor.byteOffset;
+		createInfo.normalByteOffset = normalBufferView.byteOffset + normalAccessor.byteOffset;
+		createInfo.indexByteOffset = indexBufferView.byteOffset + indexAccessor.byteOffset;
+		createInfo.indexCount = indexAccessor.count;
+		createInfo.indexType = indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort ? MeshDocument::IndexType::UInt16 : MeshDocument::IndexType::UInt32;
+
+		return { MeshDocument(std::move(createInfo)) };
+	}
+	catch (std::exception e)
+	{
+		std::cerr << "Asset System Error: Could not load file. Message: " << e.what() << std::endl;
+		return {};
+	}
 }
 
-Asset::MeshDocument Asset::LoadMeshDocument(const std::string &path)
+Asset::TextureDocument Asset::LoadTextureDocument(Sprite texture)
 {
-	MeshDocument::CreateInfo createInfo{};
-
-	const auto gltfDocument = fx::gltf::LoadFromText(path);
-	auto& primitive = gltfDocument.meshes[0].primitives[0];
-
-	auto& posAccessor = gltfDocument.accessors[primitive.attributes.find("POSITION")->second];
-	assert(posAccessor.type == fx::gltf::Accessor::Type::Vec3 && posAccessor.componentType == fx::gltf::Accessor::ComponentType::Float);
-	auto& posBufferView = gltfDocument.bufferViews[posAccessor.bufferView];
-	createInfo.posData.byteOffset = posBufferView.byteOffset + posAccessor.byteOffset;
-	createInfo.posData.byteLength = posAccessor.count * (sizeof(float) * 3);
-
-	auto& uvAccessor = gltfDocument.accessors[primitive.attributes.find("TEXCOORD_0")->second];
-	assert(uvAccessor.type == fx::gltf::Accessor::Type::Vec2 && uvAccessor.componentType == fx::gltf::Accessor::ComponentType::Float);
-	auto& uvBufferView = gltfDocument.bufferViews[uvAccessor.bufferView];
-	createInfo.uvData.byteOffset = uvBufferView.byteOffset + uvAccessor.byteOffset;
-	createInfo.uvData.byteLength = uvAccessor.count * (sizeof(float) * 2);
-
-	auto& normalAccessor = gltfDocument.accessors[primitive.attributes.find("NORMAL")->second];
-	assert(normalAccessor.type == fx::gltf::Accessor::Type::Vec3 && normalAccessor.componentType == fx::gltf::Accessor::ComponentType::Float);
-	auto& normalBufferView = gltfDocument.bufferViews[normalAccessor.bufferView];
-	createInfo.normalData.byteOffset = normalBufferView.byteOffset + normalAccessor.byteOffset;
-	createInfo.normalData.byteLength = normalAccessor.count * (sizeof(float) * 3);
-
-	assert(posAccessor.count == uvAccessor.count);
-
-	auto& indexAccessor = gltfDocument.accessors[primitive.indices];
-	assert(indexAccessor.type == fx::gltf::Accessor::Type::Scalar);
-	assert(indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort
-		   || indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedInt);
-	auto& indexBufferView = gltfDocument.bufferViews[indexAccessor.bufferView];
-	createInfo.indexData.byteOffset = indexBufferView.byteOffset + indexAccessor.byteOffset;
-	createInfo.indexData.byteLength = indexBufferView.byteLength;
-	createInfo.indexType = indexAccessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort ? MeshDocument::IndexType::Uint16 : MeshDocument::IndexType::Uint32;
-
-	createInfo.byteArray = std::move(gltfDocument.buffers[posBufferView.buffer].data);
+	TextureDocument::CreateInfo createInfo{};
 
-	return MeshDocument(std::move(createInfo));
+	return TextureDocument(std::move(createInfo));
 }
 
-Asset::TextureDocument Asset::LoadTextureDocument(Sprite texture)
+std::optional<Engine::Renderer::MeshDocument> Asset::LoadMesh(size_t i)
 {
-	TextureDocument::CreateInfo createInfo{};
+	auto path = GetMeshPath(i);
+	if (path == "")
+		return {};
 
-	// Grab pixels as char array from image.
-	int32_t x = 0;
-	int32_t y = 0;
-	int32_t channelCount = 0;
-	constexpr int32_t desiredChannelCount = 4;
-	auto pixels = stbi_load(Asset::GetPath(texture).c_str(), &x, &y, &channelCount, desiredChannelCount);
-	assert(pixels);
-	// Weird STBI API stuff
-	if constexpr (desiredChannelCount != 0)
-		channelCount = desiredChannelCount;
+	auto assetMeshDocOpt = LoadMeshDocument(path);
+	if (assetMeshDocOpt.has_value() == false)
+		return {};
 
-	createInfo.byteArray = pixels;
-	createInfo.channelCount = static_cast<uint8_t>(channelCount);
+	auto oldInfo = MeshDocument::ToCreateInfo(std::move(assetMeshDocOpt.value()));
 
-	using ValueType = decltype(createInfo.dimensions)::ValueType;
-	createInfo.dimensions = { static_cast<ValueType>(x), static_cast<ValueType>(y) };
+	using namespace Engine;
+	Renderer::MeshDocument::CreateInfo newInfo;
+	newInfo.byteArray = std::move(oldInfo.byteArray);
+	newInfo.vertexCount = std::move(oldInfo.vertexCount);
+	newInfo.indexCount = std::move(oldInfo.indexCount);
+	newInfo.indexType = oldInfo.indexType == MeshDocument::IndexType::UInt16 ? Renderer::MeshDocument::IndexType::UInt16 : Renderer::MeshDocument::IndexType::UInt32;
 
-	return TextureDocument(std::move(createInfo));
-}
+	newInfo.posByteOffset = std::move(oldInfo.posByteOffset);
+	newInfo.uvByteOffset = std::move(oldInfo.uvByteOffset);
+	newInfo.normalByteOffset = std::move(oldInfo.normalByteOffset);
+	newInfo.tangentByteOffset = std::move(oldInfo.tangentByteOffset);
+	newInfo.indexByteOffset = std::move(oldInfo.indexByteOffset);
 
-Engine::Renderer::MeshDocument Asset::LoadMesh(size_t i)
-{
-	return Engine::Renderer::MeshDocument();
+	return Renderer::MeshDocument(std::move(newInfo));
 }
 
 static Asset::MeshDocument::IndexType ToIndexType(fx::gltf::Accessor::ComponentType componentType)
@@ -160,56 +155,61 @@ static Asset::MeshDocument::IndexType ToIndexType(fx::gltf::Accessor::ComponentT
 	switch (componentType)
 	{
 	case fx::gltf::Accessor::ComponentType::UnsignedShort:
-		return Asset::MeshDocument::IndexType::Uint16;
+		return Asset::MeshDocument::IndexType::UInt16;
 	case fx::gltf::Accessor::ComponentType::UnsignedInt:
-		return Asset::MeshDocument::IndexType::Uint32;
+		return Asset::MeshDocument::IndexType::UInt32;
 	default:
 		return static_cast<Asset::MeshDocument::IndexType>(-1);
 	}
 }
 
-Asset::MeshDocument::MeshDocument(CreateInfo&& info) :
-	byteArray(std::move(info.byteArray))
+Asset::MeshDocument::CreateInfo Asset::MeshDocument::ToCreateInfo(MeshDocument&& input)
 {
-	data[static_cast<size_t>(Attribute::Position)] = info.posData;
-	data[static_cast<size_t>(Attribute::TexCoord)] = info.uvData;
-	data[static_cast<size_t>(Attribute::Normal)] = info.normalData;
-	data[static_cast<size_t>(Attribute::Index)] = info.indexData;
-	indexType = info.indexType;
-}
-
-const std::vector<uint8_t>& Asset::MeshDocument::GetByteArray() const { return byteArray; }
+	CreateInfo returnValue;
 
-size_t Asset::MeshDocument::GetTotalByteLength() const
-{
-	size_t totalLength = 0;
-	for (const auto& item : data)
-		totalLength += item.byteLength;
-	return totalLength;
-}
+	returnValue.byteArray = std::move(input.byteArray);
+	returnValue.vertexCount = std::move(input.vertexCount);
+	returnValue.indexType = std::move(input.indexType);
+	returnValue.indexCount = std::move(input.indexCount);
 
-Asset::MeshDocument::IndexType Asset::MeshDocument::GetIndexType() const { return indexType; }
+	returnValue.posByteOffset = std::move(input.GetByteOffset(Attribute::Position));
+	returnValue.uvByteOffset = std::move(input.GetByteOffset(Attribute::TexCoord));
+	returnValue.normalByteOffset = std::move(input.GetByteOffset(Attribute::Normal));
+	returnValue.tangentByteOffset = std::move(input.GetByteOffset(Attribute::Tangent));
+	returnValue.indexByteOffset = std::move(input.GetByteOffset(Attribute::Index));
 
-uint32_t Asset::MeshDocument::GetIndexCount() const
-{
-	return static_cast<uint32_t>(data[static_cast<size_t>(Attribute::Index)].byteLength / IndexTypeToByteSize(indexType));
+	return returnValue;
 }
 
-uint32_t Asset::MeshDocument::GetVertexCount() const
+Asset::MeshDocument::MeshDocument(CreateInfo&& info) :
+	byteArray(std::move(info.byteArray)),
+	indexType(info.indexType),
+	vertexCount(info.vertexCount),
+	indexCount(info.indexCount)
 {
-	return static_cast<uint32_t>(data[static_cast<size_t>(Attribute::Position)].byteLength / sizeof(PositionType));
+	GetByteOffset(Attribute::Position) = info.posByteOffset;
+	GetByteOffset(Attribute::TexCoord) = info.uvByteOffset;
+	GetByteOffset(Attribute::Normal) = info.normalByteOffset;
+	GetByteOffset(Attribute::Tangent) = info.normalByteOffset;
+	GetByteOffset(Attribute::Index) = info.indexByteOffset;
 }
 
+const std::vector<uint8_t>& Asset::MeshDocument::GetByteArray() const { return byteArray; }
+
+Asset::MeshDocument::IndexType Asset::MeshDocument::GetIndexType() const { return indexType; }
+
 const uint8_t* Asset::MeshDocument::GetDataPtr(Attribute type) const
 {
-	return byteArray.data() + data[static_cast<size_t>(type)].byteOffset;
+	return byteArray.data() + byteOffsets.at(size_t(type));
 }
 
-Asset::MeshDocument::Data Asset::MeshDocument::GetData(Attribute type) const { return data[static_cast<size_t>(type)]; }
+size_t& Asset::MeshDocument::GetByteOffset(Attribute type) { return byteOffsets.at(size_t(type)); }
+
+const size_t& Asset::MeshDocument::GetByteOffset(Attribute type) const { return byteOffsets.at(size_t(type)); }
 
-uint8_t Asset::MeshDocument::IndexTypeToByteSize(IndexType indexType)
+uint8_t Asset::MeshDocument::ToByteSize(IndexType indexType)
 {
-	return indexType == IndexType::Uint16 ? uint8_t(2) : uint8_t(4);
+	return indexType == IndexType::UInt16 ? uint8_t(2) : uint8_t(4);
 }
 
 Asset::TextureDocument::TextureDocument(CreateInfo&& right) :
diff --git a/src/Engine/Asset.hpp b/src/Engine/Asset.hpp
index b350dbb76028bba95a15e19ac752864a316f052f..841eb6b34b133ff7314dcce7d94c0b1097d46fa4 100644
--- a/src/Engine/Asset.hpp
+++ b/src/Engine/Asset.hpp
@@ -7,6 +7,7 @@
 #include <cstdint>
 #include <vector>
 #include <array>
+#include <optional>
 
 #include "Renderer/MeshDocument.hpp"
 
@@ -20,28 +21,29 @@ namespace Asset
 
 	enum class Sprite : uint32_t;
 	bool CheckValid(Sprite texture);
-	std::string GetPath(Sprite texture);
-	std::string GetName(Sprite texture);
 
 	enum class Mesh : uint32_t;
-	bool CheckValid(Mesh mesh);
-	std::string GetPath(Mesh mesh);
-	std::string GetName(Mesh mesh);
+	std::string GetMeshPath(size_t i);
 
 	MeshDocument LoadMeshDocument(Mesh mesh);
-	MeshDocument LoadMeshDocument(const std::string& path);
+	std::optional<MeshDocument> LoadMeshDocument(std::string_view path);
 	TextureDocument LoadTextureDocument(Sprite texture);
 
-	Engine::Renderer::MeshDocument LoadMesh(size_t i);
+	std::optional<Engine::Renderer::MeshDocument> LoadMesh(size_t i);
 }
 
 class Asset::MeshDocument
 {
 public:
+	using PositionType = std::array<float, 3>;
+	using UVType = std::array<float, 2>;
+	using NormalType = std::array<float, 3>;
+	using TangentType = std::array<float, 3>;
+
 	enum class IndexType
 	{
-		Uint16,
-		Uint32
+		UInt16,
+		UInt32
 	};
 
 	enum class Attribute
@@ -49,46 +51,51 @@ public:
 		Position,
 		TexCoord,
 		Normal,
+		Tangent,
 		Index,
 		COUNT
 	};
 
-	struct Data
-	{
-		size_t byteOffset;
-		size_t byteLength;
-	};
-
 	struct CreateInfo
 	{
 		std::vector<uint8_t> byteArray;
-		Data posData;
-		Data uvData;
-		Data normalData;
-		Data indexData;
+		size_t posByteOffset;
+		size_t uvByteOffset;
+		size_t normalByteOffset;
+		size_t tangentByteOffset;
+		size_t indexByteOffset;
 		IndexType indexType;
+		uint32_t vertexCount;
+		uint32_t indexCount;
 	};
 
-	using PositionType = std::array<float, 3>;
-	using UVType = std::array<float, 2>;
-	using NormalType = std::array<float, 3>;
-
 	MeshDocument(CreateInfo&& info);
-	MeshDocument(const MeshDocument&) = delete;
+	MeshDocument(MeshDocument&&) = default;
+	MeshDocument(const MeshDocument&) = default;
 
 	const std::vector<uint8_t>& GetByteArray() const;
-	size_t GetTotalByteLength() const;
+	const size_t& GetByteOffset(Attribute attr) const;
+	size_t GetByteLength(Attribute attr) const;
+	const uint8_t* GetDataPtr(Attribute attr) const;
+
+	uint32_t GetVertexCount() const;
+
 	IndexType GetIndexType() const;
 	uint32_t GetIndexCount() const;
-	uint32_t GetVertexCount() const;
-	const uint8_t* GetDataPtr(Attribute type) const;
-	Data GetData(Attribute type) const;
+
+	size_t GetTotalSizeRequired() const;
+
+	static uint8_t ToByteSize(IndexType indexType);
+	static CreateInfo ToCreateInfo(MeshDocument&& input);
+
+private:
+	size_t& GetByteOffset(Attribute attr);
 
 	std::vector<uint8_t> byteArray;
-	std::array<Data, static_cast<size_t>(Attribute::COUNT)> data;
+	std::array<size_t, static_cast<size_t>(Attribute::COUNT)> byteOffsets;
+	uint32_t vertexCount;
 	IndexType indexType;
-
-	static uint8_t IndexTypeToByteSize(IndexType indexType);
+	uint32_t indexCount;
 };
 
 class Asset::TextureDocument
@@ -102,7 +109,7 @@ public:
 	};
 
 	TextureDocument(CreateInfo&&);
-	TextureDocument(TextureDocument&& right);
+	TextureDocument(TextureDocument&&);
 	TextureDocument(const TextureDocument&) = delete;
 	~TextureDocument();
 
diff --git a/src/Engine/Components/MeshRenderer.cpp b/src/Engine/Components/MeshRenderer.cpp
index f1136dc0c7ef2c918d9e05cb693c3f1b1eeacce7..627ae6a1400197690bee259dca73e00ab49f52e6 100644
--- a/src/Engine/Components/MeshRenderer.cpp
+++ b/src/Engine/Components/MeshRenderer.cpp
@@ -37,8 +37,6 @@ namespace Engine
 			if (GetMesh() == newMesh)
 				return;
 
-			assert(Asset::CheckValid(newMesh));
-
 			mesh = newMesh;
 		}
 
diff --git a/src/Engine/Renderer/MeshDocument.hpp b/src/Engine/Renderer/MeshDocument.hpp
index 501fd3e5eca3b2755afd778dde962356e229b40c..70e954d1901cb63eb0e3cd205407c0bbe972f7c6 100644
--- a/src/Engine/Renderer/MeshDocument.hpp
+++ b/src/Engine/Renderer/MeshDocument.hpp
@@ -21,14 +21,6 @@ namespace Engine
 				UInt32
 			};
 
-			static uint8_t ToByteSize(IndexType type);
-
-			struct DataInfo
-			{
-				size_t byteOffset;
-				size_t byteLength;
-			};
-
 			enum class Attribute
 			{
 				Position,
@@ -42,38 +34,96 @@ namespace Engine
 			struct CreateInfo
 			{
 				std::vector<uint8_t> byteArray;
-				DataInfo posData;
-				DataInfo uvData;
-				DataInfo normalData;
-				DataInfo tangentData;
-				DataInfo indexData;
+				uint32_t vertexCount;
+				size_t posByteOffset;
+				size_t uvByteOffset;
+				size_t normalByteOffset;
+				size_t tangentByteOffset;
+				size_t indexByteOffset;
 				IndexType indexType;
+				uint32_t indexCount;
 			};
 
 			MeshDocument(CreateInfo&& createInfo);
-			MeshDocument() = default;
+			MeshDocument(MeshDocument&&) = default;
+			MeshDocument(const MeshDocument&) = default;
 
-			DataInfo GetData(Attribute attr) const;
+			const std::vector<uint8_t>& GetByteArray() const;
+			const size_t& GetByteOffset(Attribute attr) const;
+			size_t GetByteLength(Attribute attr) const;
 			const uint8_t* GetDataPtr(Attribute attr) const;
 
+			uint32_t GetVertexCount() const;
+
 			IndexType GetIndexType() const;
 			uint32_t GetIndexCount() const;
 
-			size_t GetTotalByteLength() const;
+			size_t GetTotalSizeRequired() const;
+
+			static uint8_t ToByteSize(IndexType type);
+			static CreateInfo ToCreateInfo(MeshDocument&& input);
+
+		private:
+			size_t& GetByteOffset(Attribute attr);
 
 			IndexType indexType;
+			uint32_t indexCount;
+			uint32_t vertexCount;
 			std::vector<uint8_t> byteArray;
-			std::array<DataInfo, static_cast<size_t>(Attribute::COUNT)> data;	
+			std::array<size_t, static_cast<size_t>(Attribute::COUNT)> data;
 		};
 
-		inline MeshDocument::DataInfo MeshDocument::GetData(Attribute attr) const
+		inline MeshDocument::MeshDocument(CreateInfo&& createInfo) :
+			byteArray(std::move(createInfo.byteArray)),
+			indexType(std::move(createInfo.indexType)),
+			indexCount(std::move(createInfo.indexCount)),
+			vertexCount(std::move(createInfo.vertexCount))
+		{
+			GetByteOffset(Attribute::Position) = std::move(createInfo.posByteOffset);
+			GetByteOffset(Attribute::TexCoord) = std::move(createInfo.uvByteOffset);
+			GetByteOffset(Attribute::Normal) = std::move(createInfo.normalByteOffset);
+			GetByteOffset(Attribute::Tangent) = std::move(createInfo.tangentByteOffset);
+			GetByteOffset(Attribute::Index) = std::move(createInfo.indexByteOffset);
+		}
+
+		inline const size_t& MeshDocument::GetByteOffset(Attribute attr) const
+		{
+			return data.at(size_t(attr));
+		}
+
+		inline size_t MeshDocument::GetByteLength(Attribute attr) const
+		{
+			switch (attr)
+			{
+			case Attribute::Position:
+				return GetVertexCount() * sizeof(PositionType);
+			case Attribute::TexCoord:
+				return GetVertexCount() * sizeof(UVType);
+			case Attribute::Normal:
+				return GetVertexCount() * sizeof(NormalType);
+			case Attribute::Tangent:
+				return GetVertexCount() * sizeof(TangentType);
+			case Attribute::Index:
+				return GetIndexCount() * ToByteSize(GetIndexType());
+			default:
+				assert(false);
+				return 0;
+			}
+		}
+
+		inline size_t& MeshDocument::GetByteOffset(Attribute attr)
 		{
 			return data.at(static_cast<size_t>(attr));
 		}
 
 		inline const uint8_t* MeshDocument::GetDataPtr(Attribute attr) const
 		{
-			return byteArray.data() + GetData(attr).byteOffset;
+			return byteArray.data() + GetByteOffset(attr);
+		}
+
+		inline uint32_t MeshDocument::GetVertexCount() const
+		{
+			return vertexCount;
 		}
 
 		inline MeshDocument::IndexType MeshDocument::GetIndexType() const
@@ -83,10 +133,10 @@ namespace Engine
 
 		inline uint32_t MeshDocument::GetIndexCount() const
 		{
-			return uint32_t( GetData( Attribute::Index).byteLength / ToByteSize(GetIndexType() ) );
+			return indexCount;
 		}
 
-		inline size_t MeshDocument::GetTotalByteLength() const
+		inline size_t MeshDocument::GetTotalSizeRequired() const
 		{
 			return data.size();
 		}
@@ -95,5 +145,21 @@ namespace Engine
 		{
 			return type == IndexType::UInt16 ? uint8_t(2) : uint8_t(4);
 		}
+
+		inline MeshDocument::CreateInfo MeshDocument::ToCreateInfo(MeshDocument&& input)
+		{
+			CreateInfo returnValue;
+
+			returnValue.byteArray = std::move(input.byteArray);
+			returnValue.vertexCount = std::move(input.vertexCount);
+			returnValue.indexType = std::move(input.indexType);
+			returnValue.indexCount = std::move(input.indexCount);
+
+			returnValue.posByteOffset = std::move(input.GetByteOffset(Attribute::Position));
+			returnValue.uvByteOffset = std::move(input.GetByteOffset(Attribute::TexCoord));
+			returnValue.normalByteOffset = std::move(input.GetByteOffset(Attribute::Normal));
+			returnValue.tangentByteOffset = std::move(input.GetByteOffset(Attribute::Tangent));
+			returnValue.indexByteOffset = std::move(input.GetByteOffset(Attribute::Index));
+		}
 	}
 }
\ No newline at end of file
diff --git a/src/Engine/Renderer/OpenGL.cpp b/src/Engine/Renderer/OpenGL.cpp
index 9459f736a7b7985b01fa466f11a4f9d76aa81830..a6a7d0e81cce6eacd9b2e1b262f056a68a241364 100644
--- a/src/Engine/Renderer/OpenGL.cpp
+++ b/src/Engine/Renderer/OpenGL.cpp
@@ -513,7 +513,11 @@ namespace Engine
 
 	std::optional<Renderer::OpenGL::VBO> Renderer::OpenGL::VBOFromPath(size_t id)
 	{
-		const auto meshDocument = Core::GetData().assetLoadData.meshLoader(id);
+		const auto meshDocumentOpt = Core::GetData().assetLoadData.meshLoader(id);
+
+		assert(meshDocumentOpt.has_value());
+
+		const auto& meshDocument = meshDocumentOpt.value();
 
 		VBO vbo;
 
@@ -523,25 +527,25 @@ namespace Engine
 		glGenVertexArrays(1, &vbo.vertexArrayObject);
 		glBindVertexArray(vbo.vertexArrayObject);
 
-		glGenBuffers(static_cast<GLint>(vbo.attributeBuffers.size()), vbo.attributeBuffers.data());
+		glGenBuffers(GLint(vbo.attributeBuffers.size()), vbo.attributeBuffers.data());
 
-		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Position)]);
-		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Position).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Position), GL_STATIC_DRAW);
-		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Position));
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[size_t(VBO::Attribute::Position)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetByteLength(MeshDocument::Attribute::Position), meshDocument.GetDataPtr(MeshDocument::Attribute::Position), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(size_t(VBO::Attribute::Position));
 		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
-		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::TexCoord)]);
-		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::TexCoord).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::TexCoord), GL_STATIC_DRAW);
-		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::TexCoord));
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[size_t(VBO::Attribute::TexCoord)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetByteLength(MeshDocument::Attribute::TexCoord), meshDocument.GetDataPtr(MeshDocument::Attribute::TexCoord), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(size_t(VBO::Attribute::TexCoord));
 		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
 
-		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Normal)]);
-		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Normal).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Normal), GL_STATIC_DRAW);
-		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Normal));
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[size_t(VBO::Attribute::Normal)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetByteLength(MeshDocument::Attribute::Normal), meshDocument.GetDataPtr(MeshDocument::Attribute::Normal), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(size_t(VBO::Attribute::Normal));
 		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
-		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Index)]);
-		glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Index).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Index), GL_STATIC_DRAW);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.attributeBuffers[size_t(VBO::Attribute::Index)]);
+		glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshDocument.GetByteLength(MeshDocument::Attribute::Index), meshDocument.GetDataPtr(MeshDocument::Attribute::Index), GL_STATIC_DRAW);
 
 		return vbo;
 	}
diff --git a/src/Engine/Renderer/Renderer.hpp b/src/Engine/Renderer/Renderer.hpp
index a7242b18ca8b3c5c6f8bbbc03d3d4803a8999d4b..9ccf32c6551c1038e291f9533b3725e848ad492b 100644
--- a/src/Engine/Renderer/Renderer.hpp
+++ b/src/Engine/Renderer/Renderer.hpp
@@ -62,7 +62,7 @@ namespace Engine
 
 	struct Renderer::AssetLoadCreateInfo
 	{
-		using MeshLoaderPFN = MeshDocument(*)(size_t);
+		using MeshLoaderPFN = std::optional<MeshDocument>(*)(size_t);
 		MeshLoaderPFN meshLoader = nullptr;
 	};
 
diff --git a/src/Engine/Renderer/TextureDocument.hpp b/src/Engine/Renderer/TextureDocument.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fce68b392c6d828a5cf9cce8edb7f190287d1f8c
--- /dev/null
+++ b/src/Engine/Renderer/TextureDocument.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <array>
+#include <vector>
+#include <cstddef>
+
+namespace Engine
+{
+	namespace Renderer
+	{
+		class TextureDocument
+		{
+		public:
+			enum class Format;
+
+		private:
+			Format format;
+			std::array<uint32_t, 2> dimensions;
+			std::array<uint8_t> byteArray;
+		};
+
+		enum class TextureDocument::Format
+		{
+			RGBA
+		};
+	}
+}
\ No newline at end of file