From 6f42d60e8ee6472ffcc3e366655473361e1349d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Susanne=20D=C3=B6tsch?= <susannedoetsch@uni-koblenz.de>
Date: Sat, 10 Jul 2021 12:31:55 +0200
Subject: [PATCH] [79] Finished loadScene and probeScene

Programmed the two functions, loadMesh still copies all textures
---
 .../include/vkcv/asset/asset_loader.hpp       |   6 +
 .../src/vkcv/asset/asset_loader.cpp           | 238 ++++++++++++++++--
 2 files changed, 223 insertions(+), 21 deletions(-)

diff --git a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
index c250b4a8..2c95a0e9 100644
--- a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
+++ b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
@@ -227,12 +227,18 @@ typedef struct {
  */
 int loadScene(const std::filesystem::path &path, Scene &scene);
 
+int probeScene(const std::filesystem::path &path, Scene &scene);
+
+int loadMesh(const std::filesystem::path& path, Scene& scene, std::string name);
+
+
 struct TextureData {
     int width;
     int height;
     int componentCount;
     std::vector<char*> data;
 };
+
 TextureData loadTexture(const std::filesystem::path& path);
 
 }
diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
index 83d0b477..0b21120b 100644
--- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
+++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
@@ -383,7 +383,7 @@ int createVertexGroups(fx::gltf::Mesh const& objectMesh,
 	fx::gltf::Document &sceneObjects, 
 	std::vector<VertexGroup> &vertexGroups,
 	std::vector<int> &vertexGroupsIndices,
-	int &groupCount) {
+	int &groupCount, bool probe) {
 
 	const size_t numVertexGroups = objectMesh.primitives.size();
 	vertexGroups.reserve(numVertexGroups);
@@ -415,8 +415,8 @@ int createVertexGroups(fx::gltf::Mesh const& objectMesh,
 
 		IndexType indexType;
 		std::vector<uint8_t> indexBufferData = {};
-		if (objectPrimitive.indices >= 0) { // if there is no index buffer, -1 is returned from fx-gltf
-			const fx::gltf::Accessor& indexAccessor = sceneObjects.accessors[objectPrimitive.indices];
+		const fx::gltf::Accessor& indexAccessor = sceneObjects.accessors[objectPrimitive.indices];
+		if (objectPrimitive.indices >= 0 && !probe) { // if there is no index buffer, -1 is returned from fx-gltf
 			const fx::gltf::BufferView& indexBufferView = sceneObjects.bufferViews[indexAccessor.bufferView];
 			const fx::gltf::Buffer& indexBuffer = sceneObjects.buffers[indexBufferView.buffer];
 
@@ -429,12 +429,11 @@ int createVertexGroups(fx::gltf::Mesh const& objectMesh,
 					return ASSET_ERROR;
 				}
 			}
-
-			indexType = getIndexType(indexAccessor.componentType);
-			if (indexType == IndexType::UNDEFINED) {
-				vkcv_log(LogLevel::ERROR, "Index Type undefined or not supported.");
-				return ASSET_ERROR;
-			}
+		}
+		indexType = getIndexType(indexAccessor.componentType);
+		if (indexType == IndexType::UNDEFINED) {
+			vkcv_log(LogLevel::ERROR, "Index Type undefined or not supported.");
+			return ASSET_ERROR;
 		}
 
 		const fx::gltf::BufferView& vertexBufferView = sceneObjects.bufferViews[posAccessor.bufferView];
@@ -452,20 +451,22 @@ int createVertexGroups(fx::gltf::Mesh const& objectMesh,
 
 		// FIXME: This only works when all vertex attributes are in one buffer
 		std::vector<uint8_t> vertexBufferData;
-		vertexBufferData.resize(relevantBufferSize);
-		{
-			const void* const ptr = ((char*)vertexBuffer.data.data()) + relevantBufferOffset;
-			if (!memcpy(vertexBufferData.data(), ptr, relevantBufferSize)) {
-				vkcv_log(LogLevel::ERROR, "Copying vertex buffer data");
-				return ASSET_ERROR;
+		if (!probe) {
+			vertexBufferData.resize(relevantBufferSize);
+			{
+				const void* const ptr = ((char*)vertexBuffer.data.data()) + relevantBufferOffset;
+				if (!memcpy(vertexBufferData.data(), ptr, relevantBufferSize)) {
+					vkcv_log(LogLevel::ERROR, "Copying vertex buffer data");
+					return ASSET_ERROR;
+				}
 			}
-		}
 
-		// make vertex attributes relative to copied section
-		for (auto& attribute : vertexAttributes) {
-			attribute.offset -= relevantBufferOffset;
+			// make vertex attributes relative to copied section
+			for (auto& attribute : vertexAttributes) {
+				attribute.offset -= relevantBufferOffset;
+			}
 		}
-
+		
 		vertexGroups.push_back({
 			static_cast<PrimitiveMode>(objectPrimitive.mode),
 			sceneObjects.accessors[objectPrimitive.indices].count,
@@ -579,7 +580,7 @@ int loadScene(const std::filesystem::path &path, Scene &scene){
         std::vector<int> vertexGroupsIndices;
         fx::gltf::Mesh const &objectMesh = sceneObjects.meshes[i];
 
-		if (createVertexGroups(objectMesh, sceneObjects, vertexGroups, vertexGroupsIndices, groupCount) != ASSET_SUCCESS) {
+		if (createVertexGroups(objectMesh, sceneObjects, vertexGroups, vertexGroupsIndices, groupCount, false) != ASSET_SUCCESS) {
 			vkcv_log(LogLevel::ERROR, "Failed to get Vertex Groups!");
 			return ASSET_ERROR;
 		}
@@ -654,4 +655,199 @@ TextureData loadTexture(const std::filesystem::path& path) {
     return texture;
 }
 
+int probeScene(const std::filesystem::path& path, Scene& scene) {
+	fx::gltf::Document sceneObjects;
+
+	try {
+		if (path.extension() == ".glb") {
+			sceneObjects = fx::gltf::LoadFromBinary(path.string());
+		}
+		else {
+			sceneObjects = fx::gltf::LoadFromText(path.string());
+		}
+	}
+	catch (const std::system_error& err) {
+		recurseExceptionPrint(err, path.string());
+		return ASSET_ERROR;
+	}
+	catch (const std::exception& e) {
+		recurseExceptionPrint(e, path.string());
+		return ASSET_ERROR;
+	}
+	auto dir = path.parent_path().string();
+
+	// file has to contain at least one mesh
+	if (sceneObjects.meshes.empty()) {
+		return ASSET_ERROR;
+	}
+
+	std::vector<Material> materials;
+	std::vector<Texture> textures;
+	std::vector<Sampler> samplers;
+	std::vector<Mesh> meshes;
+	std::vector<VertexGroup> vertexGroups;
+	int groupCount = 0;
+
+	for (size_t i = 0; i < sceneObjects.meshes.size(); i++) {
+		std::vector<int> vertexGroupsIndices;
+		fx::gltf::Mesh const& objectMesh = sceneObjects.meshes[i];
+
+		if (createVertexGroups(objectMesh, sceneObjects, vertexGroups, vertexGroupsIndices, groupCount, true) != ASSET_SUCCESS) {
+			vkcv_log(LogLevel::ERROR, "Failed to get Vertex Groups!");
+			return ASSET_ERROR;
+		}
+
+		Mesh mesh = {};
+		mesh.name = sceneObjects.meshes[i].name;
+		mesh.vertexGroups = vertexGroupsIndices;
+
+		meshes.push_back(mesh);
+	}
+
+	// This only works if the node has a mesh and it only loads the meshes and ignores cameras and lights
+	for (auto& node : sceneObjects.nodes) {
+		if (node.mesh > -1) {
+			meshes[node.mesh].modelMatrix = computeModelMatrix(
+				node.translation,
+				node.scale,
+				node.rotation,
+				node.matrix
+			);
+		}
+	}
+
+	/*if (createTextures(sceneObjects.textures, sceneObjects.images, sceneObjects.buffers, sceneObjects.bufferViews, dir, textures) != ASSET_SUCCESS) {
+		size_t missing = sceneObjects.textures.size() - textures.size();
+		vkcv_log(LogLevel::ERROR, "Failed to get %lu textures from glTF source '%s'",
+			missing, path.c_str());
+	}*/
+
+
+	if (createMaterial(sceneObjects, materials) != ASSET_SUCCESS) {
+		vkcv_log(LogLevel::ERROR, "Failed to get Materials!");
+		return ASSET_ERROR;
+	}
+
+	/*samplers.reserve(sceneObjects.samplers.size());
+	for (const auto& it : sceneObjects.samplers) {
+		samplers.push_back({});
+		auto& sampler = samplers.back();
+		if (translateSampler(it, sampler) != ASSET_SUCCESS) {
+			return ASSET_ERROR;
+		}
+	}*/
+
+	scene = {
+			meshes,
+			vertexGroups,
+			materials,
+			textures,
+			samplers
+	};
+
+	return ASSET_SUCCESS;
+}
+
+
+int loadMesh(const std::filesystem::path& path, Scene& scene, std::string name) {
+	fx::gltf::Document sceneObjects;
+
+	try {
+		if (path.extension() == ".glb") {
+			sceneObjects = fx::gltf::LoadFromBinary(path.string());
+		}
+		else {
+			sceneObjects = fx::gltf::LoadFromText(path.string());
+		}
+	}
+	catch (const std::system_error& err) {
+		recurseExceptionPrint(err, path.string());
+		return ASSET_ERROR;
+	}
+	catch (const std::exception& e) {
+		recurseExceptionPrint(e, path.string());
+		return ASSET_ERROR;
+	}
+	auto dir = path.parent_path().string();
+
+	// file has to contain at least one mesh
+	if (sceneObjects.meshes.empty()) {
+		return ASSET_ERROR;
+	}
+
+	std::vector<Material> materials;
+	std::vector<Texture> textures;
+	std::vector<Sampler> samplers;
+	std::vector<Mesh> meshes;
+	std::vector<VertexGroup> vertexGroups;
+	int groupCount = 0;
+	int meshIndex = -1;
+
+	for (size_t i = 0; i < sceneObjects.meshes.size(); i++) {
+		if (sceneObjects.meshes[i].name == name) {
+			std::vector<int> vertexGroupsIndices;
+			fx::gltf::Mesh const& objectMesh = sceneObjects.meshes[i];
+
+			if (createVertexGroups(objectMesh, sceneObjects, vertexGroups, vertexGroupsIndices, groupCount, false) != ASSET_SUCCESS) {
+				vkcv_log(LogLevel::ERROR, "Failed to get Vertex Groups!");
+				return ASSET_ERROR;
+			}
+
+			Mesh mesh = {};
+			mesh.name = sceneObjects.meshes[i].name;
+			mesh.vertexGroups = vertexGroupsIndices;
+
+			meshes.push_back(mesh);
+			meshIndex = i;
+			break;
+		}
+	}
+
+	if (meshes.empty()) {
+		vkcv_log(LogLevel::ERROR, "No mesh by that name!");
+		return ASSET_ERROR;
+	}
+
+	// This only works if the node has a mesh and it only loads the meshes and ignores cameras and lights
+	if (sceneObjects.nodes[meshIndex].mesh > -1) {
+		meshes[sceneObjects.nodes[meshIndex].mesh].modelMatrix = computeModelMatrix(
+			sceneObjects.nodes[meshIndex].translation,
+			sceneObjects.nodes[meshIndex].scale,
+			sceneObjects.nodes[meshIndex].rotation,
+			sceneObjects.nodes[meshIndex].matrix
+		);
+	}
+
+	if (createTextures(sceneObjects.textures, sceneObjects.images, sceneObjects.buffers, sceneObjects.bufferViews, dir, textures) != ASSET_SUCCESS) {
+		size_t missing = sceneObjects.textures.size() - textures.size();
+		vkcv_log(LogLevel::ERROR, "Failed to get %lu textures from glTF source '%s'",
+			missing, path.c_str());
+	}
+
+
+	if (createMaterial(sceneObjects, materials) != ASSET_SUCCESS) {
+		vkcv_log(LogLevel::ERROR, "Failed to get Materials!");
+		return ASSET_ERROR;
+	}
+
+	samplers.reserve(sceneObjects.samplers.size());
+	for (const auto& it : sceneObjects.samplers) {
+		samplers.push_back({});
+		auto& sampler = samplers.back();
+		if (translateSampler(it, sampler) != ASSET_SUCCESS) {
+			return ASSET_ERROR;
+		}
+	}
+
+	scene = {
+			meshes,
+			vertexGroups,
+			materials,
+			textures,
+			samplers
+	};
+
+	return ASSET_SUCCESS;
+}
+
 }
-- 
GitLab