From 91bdbe4a09b89ed3570431f35555bb424b9d459c Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Thu, 23 Jan 2025 17:19:53 +0100 Subject: [PATCH] Adding model loading and bvh generation --- CMakeLists.txt | 12 +-------- cube.fbx | Bin 0 -> 15244 bytes src/CMakeLists.txt | 1 + src/main.cpp | 5 ++++ src/scene/AABB.h | 38 ++++++++++++++++++++++++++++ src/scene/BVH.cpp | 52 ++++++++++++++++++++++++++++++++++++++- src/scene/BVH.h | 29 +++++++++++++++------- src/scene/CMakeLists.txt | 3 +++ src/util/CMakeLists.txt | 1 + src/util/Model.h | 3 ++- src/util/ModelLoader.cpp | 18 +++++++++----- src/util/ModelLoader.h | 1 + src/util/Ray.h | 0 13 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 cube.fbx create mode 100644 src/scene/AABB.h create mode 100644 src/util/Ray.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b7da388..936033f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,17 +11,6 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/external/vcpkg/scripts/buil project(RayTracer) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build) -#Workaround for vs, because it places artifacts into an additional subfolder -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_SOURCE_DIR}/build) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_SOURCE_DIR}/build) find_package(assimp CONFIG REQUIRED) find_package(glfw3 CONFIG REQUIRED) @@ -29,6 +18,7 @@ find_package(glm CONFIG REQUIRED) find_package(Ktx CONFIG REQUIRED) add_executable(RayTracer "") +target_include_directories(RayTracer PUBLIC src/) target_link_libraries(RayTracer PUBLIC assimp::assimp) target_link_libraries(RayTracer PUBLIC glfw) target_link_libraries(RayTracer PUBLIC glm::glm) diff --git a/cube.fbx b/cube.fbx new file mode 100644 index 0000000000000000000000000000000000000000..0c8add83891b1302f99fbf4b3e08fd1649d62daa GIT binary patch literal 15244 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 literal 0 HcmV?d00001 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b42a2ac..0c915d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,3 +4,4 @@ target_sources(RayTracer add_subdirectory(scene/) add_subdirectory(window/) +add_subdirectory(util/) diff --git a/src/main.cpp b/src/main.cpp index 90d2268..69ebc94 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,11 @@ #include "window/Window.h" +#include "util/ModelLoader.h" +#include "scene/BVH.h" int main() { + BVH bvh; + bvh.addModels(ModelLoader::loadModel("../../cube.fbx")); + bvh.generate(); Window w(1920, 1080); while (true) { w.update(); diff --git a/src/scene/AABB.h b/src/scene/AABB.h new file mode 100644 index 0000000..f11ea1e --- /dev/null +++ b/src/scene/AABB.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +struct AABB +{ + glm::vec3 min = glm::vec3(std::numeric_limits::max()); + glm::vec3 max = glm::vec3(std::numeric_limits::lowest()); + float surfaceArea() const + { + glm::vec3 d = glm::vec3(max.x - min.x, max.y - min.y, max.z - min.z); + return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x); + } + void adjust(glm::vec3 pos) + { + min.x = std::min(min.x, pos.x); + min.y = std::min(min.y, pos.y); + min.z = std::min(min.z, pos.z); + + max.x = std::max(max.x, pos.x); + max.y = std::max(max.y, pos.y); + max.z = std::max(max.z, pos.z); + } + static AABB combine(AABB lhs, AABB rhs) + { + AABB result; + + result.min.x = std::min(lhs.min.x, rhs.min.x); + result.min.y = std::min(lhs.min.y, rhs.min.y); + result.min.z = std::min(lhs.min.z, rhs.min.z); + + result.max.x = std::max(lhs.max.x, rhs.max.x); + result.max.y = std::max(lhs.max.y, rhs.max.y); + result.max.z = std::max(lhs.max.z, rhs.max.z); + + return result; + } +}; diff --git a/src/scene/BVH.cpp b/src/scene/BVH.cpp index 6e24743..e0c1703 100644 --- a/src/scene/BVH.cpp +++ b/src/scene/BVH.cpp @@ -1 +1,51 @@ -#include "BVH.h" \ No newline at end of file +#include "BVH.h" +#include + +void BVH::addModel(PModel model) { models.push_back(std::move(model)); } + +void BVH::addModels(std::vector _models) +{ + for (int i = 0; i < _models.size(); ++i) + { + models.push_back(std::move(_models[i])); + } +} + +void BVH::generate() +{ + std::vector pendingNodes; + while (!models.empty()) + { + pendingNodes.push_back(std::make_unique(std::move(models.back()))); + models.pop_back(); + } + while (pendingNodes.size() > 1) + { + int lhs = pendingNodes.size(); + int rhs = pendingNodes.size(); + float minSurface = std::numeric_limits::max(); + for (int i = 0; i < pendingNodes.size(); ++i) + { + for (int j = 0; j < pendingNodes.size(); ++j) + { + if (i == j) + continue; + AABB combined = AABB::combine(pendingNodes[i]->aabb, pendingNodes[j]->aabb); + float surface = combined.surfaceArea(); + if (minSurface > surface) + { + lhs = i; + rhs = j; + minSurface = surface; + } + } + } + PNode newNode = std::make_unique(AABB::combine(pendingNodes[lhs]->aabb, pendingNodes[rhs]->aabb)); + newNode->left = std::move(pendingNodes[lhs]); + newNode->right = std::move(pendingNodes[rhs]); + pendingNodes.erase(pendingNodes.begin() + lhs); + pendingNodes.erase(pendingNodes.begin() + rhs); + pendingNodes.push_back(std::move(newNode)); + } + hierarchy = std::move(pendingNodes[0]); +} diff --git a/src/scene/BVH.h b/src/scene/BVH.h index 5aae953..28cb6f9 100644 --- a/src/scene/BVH.h +++ b/src/scene/BVH.h @@ -1,15 +1,26 @@ #pragma once -#include +#include "AABB.h" +#include "util/Model.h" #include -struct AABB { - glm::vec3 min; - glm::vec3 max; -}; - class BVH { -public: -private: - std::vector boundingBoxes; + public: + void addModel(PModel model); + void addModels(std::vector models); + void generate(); + + private: + DECLARE_REF(Node) + struct Node + { + PNode left; + PNode right; + AABB aabb; + PModel model; + Node(AABB aabb) : aabb(aabb) {} + Node(PModel model) : aabb(model->boundingBox), model(std::move(model)) {} + }; + PNode hierarchy; + std::vector models; }; \ No newline at end of file diff --git a/src/scene/CMakeLists.txt b/src/scene/CMakeLists.txt index 3319d65..2156aa6 100644 --- a/src/scene/CMakeLists.txt +++ b/src/scene/CMakeLists.txt @@ -1,4 +1,7 @@ target_sources(RayTracer PRIVATE + AABB.h + BVH.h + BVH.cpp Scene.h Scene.cpp) \ No newline at end of file diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 8e79e3f..4d96c4f 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -4,4 +4,5 @@ target_sources(RayTracer Model.cpp ModelLoader.h ModelLoader.cpp + Ray.h ) \ No newline at end of file diff --git a/src/util/Model.h b/src/util/Model.h index efee0e6..8d884d4 100644 --- a/src/util/Model.h +++ b/src/util/Model.h @@ -1,11 +1,12 @@ #pragma once #include "Minimal.h" +#include "scene/AABB.h" #include -#include class Model { public: + AABB boundingBox; std::vector positions; std::vector indices; }; diff --git a/src/util/ModelLoader.cpp b/src/util/ModelLoader.cpp index 793d2a3..b96b618 100644 --- a/src/util/ModelLoader.cpp +++ b/src/util/ModelLoader.cpp @@ -8,22 +8,28 @@ std::vector ModelLoader::loadModel(std::string_view filename) { Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(filename, 0); + const aiScene* scene = importer.ReadFile(std::string(filename), aiProcess_Triangulate); + std::vector result; for (int m = 0; m < scene->mNumMeshes; ++m) { - PModel result = std::make_unique(); + PModel model = std::make_unique(); const aiMesh* mesh = scene->mMeshes[m]; + AABB aabb; for (int v = 0; v < mesh->mNumVertices; ++v) { auto aiVert = mesh->mVertices[v]; - result->positions.add(glm::vec3(aiVert.x, aiVert.y, aiVert.z)); + model->positions.push_back(glm::vec3(aiVert.x, aiVert.y, aiVert.z)); + aabb.adjust(model->positions.back()); } for (int i = 0; i < mesh->mNumFaces; ++i) { auto face = mesh->mFaces[i]; - result->indices.add(face.mIndices[0]); - result->indices.add(face.mIndices[1]); - result->indices.add(face.mIndices[2]); + model->indices.push_back(face.mIndices[0]); + model->indices.push_back(face.mIndices[1]); + model->indices.push_back(face.mIndices[2]); } + model->boundingBox = aabb; + result.push_back(std::move(model)); } + return result; } diff --git a/src/util/ModelLoader.h b/src/util/ModelLoader.h index 4632a5a..a1c0476 100644 --- a/src/util/ModelLoader.h +++ b/src/util/ModelLoader.h @@ -1,5 +1,6 @@ #pragma once #include "Model.h" +#include class ModelLoader { diff --git a/src/util/Ray.h b/src/util/Ray.h new file mode 100644 index 0000000..e69de29