From 60e8548c7d5b6667d93071e828d7983aa8b443f2 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Sat, 25 Jan 2025 19:14:22 +0100 Subject: [PATCH] reorganizing mesh data --- src/scene/BVH.cpp | 72 +++++++++++++++++++++++++++++++++++++--- src/scene/BVH.h | 17 ++++++++-- src/util/Model.cpp | 57 ++----------------------------- src/util/Model.h | 3 +- src/util/ModelLoader.cpp | 45 ++++++++++++------------- 5 files changed, 108 insertions(+), 86 deletions(-) diff --git a/src/scene/BVH.cpp b/src/scene/BVH.cpp index 77ec76d..80ccfaf 100644 --- a/src/scene/BVH.cpp +++ b/src/scene/BVH.cpp @@ -22,7 +22,23 @@ void BVH::generate() std::vector pendingNodes; while (!models.empty()) { - pendingNodes.push_back(std::make_unique(std::move(models.back()))); + auto& model = models.back(); + ModelReference ref = { + .positionOffset = (uint32_t)positionPool.size(), + .indicesOffset = (uint32_t)indicesPool.size(), + .numIndices = (uint32_t)model->indices.size(), + }; + for (uint32_t i = 0; i < model->positions.size(); ++i) + { + positionPool.push_back(model->positions[i]); + } + for (uint32_t i = 0; i < model->indices.size(); ++i) + { + indicesPool.push_back(model->indices[i]); + edgesPool.push_back(model->edges[i]); + faceNormalsPool.push_back(model->faceNormals[i]); + } + pendingNodes.push_back(std::make_unique(model->boundingBox, ref)); models.pop_back(); } while (pendingNodes.size() > 1) @@ -82,9 +98,9 @@ std::vector BVH::generateIntersections(const PNode& currentNod { return {}; } - if (currentNode->model != nullptr) + if (currentNode->model.numIndices > 0) { - auto result = currentNode->model->intersect(ray); + auto result = intersectModel(currentNode->model, ray); if (result.has_value()) { return {*result}; @@ -102,4 +118,52 @@ std::vector BVH::generateIntersections(const PNode& currentNod leftResults.push_back(std::move(it)); } return leftResults; -} \ No newline at end of file +} + +std::optional BVH::intersectModel(ModelReference reference, const Ray ray) const +{ + std::optional intersection = {}; + float distance = 0; + + for (size_t posIndex = 0, edgeIndex = 0, normalIndex = 0; posIndex < reference.numIndices; posIndex++, edgeIndex += 2, normalIndex++) + { + const auto p0 = positionPool[reference.positionOffset + indicesPool[reference.indicesOffset + posIndex].x]; + const auto p1 = positionPool[reference.positionOffset + indicesPool[reference.indicesOffset + posIndex].y]; + const auto p2 = positionPool[reference.positionOffset + indicesPool[reference.indicesOffset + posIndex].z]; + + const auto e0 = edgesPool[reference.indicesOffset + edgeIndex]; + const auto e1 = edgesPool[reference.indicesOffset + edgeIndex + 1]; + + const auto n = faceNormalsPool[reference.indicesOffset + normalIndex]; + + const auto s = ray.origin - p0; + const auto s1 = glm::cross(ray.direction, e1); + const auto s2 = glm::cross(s, e0); + + const float fraction = 1.0f / glm::dot(s1, e0); + const auto resultVector = glm::vec3(glm::dot(s2, e1), glm::dot(s1, s), glm::dot(s2, ray.direction)) * fraction; + + const float b3 = 1.0f - resultVector.y - resultVector.z; + + if (b3 < 0 || b3 > 1) + continue; + if (resultVector.y < 0 || resultVector.y > 1) + continue; + if (resultVector.z < 0 || resultVector.z > 1) + continue; + + if (resultVector.x < 1e-6) + continue; + + if (!intersection.has_value() || resultVector.x < distance) + { + intersection = IntersectionInfo{.position = ray.origin + ray.direction * resultVector.x, + .normal = n, + .albedo = glm::vec3(0.7f, 0.7f, 0.7f), + .emissive = glm::vec3(0.0f, 0.0f, 0.0f)}; + distance = resultVector.x; + } + } + + return intersection; +} diff --git a/src/scene/BVH.h b/src/scene/BVH.h index be8fe2d..c90908b 100644 --- a/src/scene/BVH.h +++ b/src/scene/BVH.h @@ -6,6 +6,13 @@ #include #include +struct ModelReference +{ + uint32_t positionOffset; + uint32_t indicesOffset; + uint32_t numIndices; +}; + class BVH { public: @@ -16,18 +23,24 @@ public: std::optional traceRay(Ray ray) const; private: + std::vector positionPool; + std::vector indicesPool; + std::vector edgesPool; + std::vector faceNormalsPool; + DECLARE_REF(Node) struct Node { PNode left; PNode right; AABB aabb; - PModel model; + ModelReference model; Node(AABB aabb) : aabb(aabb) {} - Node(PModel model) : aabb(model->boundingBox), model(std::move(model)) {} + Node(AABB aabb, ModelReference model) : aabb(aabb), model(model) {} }; PNode hierarchy; std::vector models; std::vector generateIntersections(const PNode& currentNode, Ray ray) const; + std::optional intersectModel(ModelReference reference, Ray ray) const; }; \ No newline at end of file diff --git a/src/util/Model.cpp b/src/util/Model.cpp index 706b2ea..aa73bc1 100644 --- a/src/util/Model.cpp +++ b/src/util/Model.cpp @@ -9,64 +9,13 @@ void Model::transform(glm::mat4 matrix) boundingBox.transform(matrix); - for (int i = 0; i < indices.size(); i+=3) + for (int i = 0; i < indices.size(); i++) { - auto e0 = positions[indices[i + 1]] - positions[indices[i + 0]]; - auto e1 = positions[indices[i + 2]] - positions[indices[i + 0]]; + auto e0 = positions[indices[i].y] - positions[indices[i].x]; + auto e1 = positions[indices[i].z] - positions[indices[i].x]; edges.push_back(e0); edges.push_back(e1); faceNormals.push_back(glm::cross(e0, e1)); } } - -std::optional Model::intersect(const Ray ray) const -{ - std::optional intersection = {}; - float distance = 0; - - for(size_t posIndex=0, edgeIndex=0, normalIndex=0; posIndex 1) - continue; - if(resultVector.y < 0 || resultVector.y > 1) - continue; - if(resultVector.z < 0 || resultVector.z > 1) - continue; - - if(resultVector.x < 1e-6) - continue; - - if(!intersection.has_value() || resultVector.x < distance) - { - intersection = IntersectionInfo { - .position = ray.origin + ray.direction * resultVector.x, - .normal = n, - .albedo = glm::vec3(0.7f, 0.7f, 0.7f), - .emissive = glm::vec3(0.0f, 0.0f, 0.0f) - }; - distance = resultVector.x; - } - } - - return intersection; -} - diff --git a/src/util/Model.h b/src/util/Model.h index 21a4472..02bf4e5 100644 --- a/src/util/Model.h +++ b/src/util/Model.h @@ -21,10 +21,9 @@ class Model public: AABB boundingBox; std::vector positions; - std::vector indices; + std::vector indices; std::vector edges; std::vector faceNormals; void transform(glm::mat4 matrix); - std::optional intersect(Ray ray) const; }; DECLARE_REF(Model) \ No newline at end of file diff --git a/src/util/ModelLoader.cpp b/src/util/ModelLoader.cpp index 39f0dbe..2a1e67e 100644 --- a/src/util/ModelLoader.cpp +++ b/src/util/ModelLoader.cpp @@ -7,30 +7,27 @@ std::vector ModelLoader::loadModel(std::string_view filename) { - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(std::string(filename), aiProcess_Triangulate); - std::vector result; - for (int m = 0; m < scene->mNumMeshes; ++m) + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(std::string(filename), aiProcess_Triangulate); + std::vector result; + for (int m = 0; m < scene->mNumMeshes; ++m) + { + PModel model = std::make_unique(); + const aiMesh* mesh = scene->mMeshes[m]; + AABB aabb; + for (int v = 0; v < mesh->mNumVertices; ++v) { - 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]; - 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]; - 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)); + auto aiVert = mesh->mVertices[v]; + model->positions.push_back(glm::vec3(aiVert.x, aiVert.y, aiVert.z)); + aabb.adjust(model->positions.back()); } - return result; + for (int i = 0; i < mesh->mNumFaces; ++i) + { + auto face = mesh->mFaces[i]; + model->indices.push_back(glm::uvec3(face.mIndices[0], face.mIndices[1], face.mIndices[2])); + } + model->boundingBox = aabb; + result.push_back(std::move(model)); + } + return result; }