From 19d10d68d10f196072b0953e4deb46e763e0dbcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A4=8E=E5=90=8D=E6=B7=B1=E9=9B=AA?= Date: Tue, 5 Nov 2019 00:10:27 -0500 Subject: [PATCH] rewrite accel --- CMakeLists.txt | 2 +- src/api/accelerator.h | 4 +- src/api/mesh.h | 44 +-- src/api/scene.h | 7 +- src/core/accelerators/embree-backend.cpp | 43 +-- src/core/accelerators/embree-backend.h | 14 +- src/core/accelerators/sahbvh.cpp | 381 ++++++++++------------- src/core/accelerators/sahbvh.h | 148 +-------- src/core/graph.cpp | 10 +- src/core/scene.cpp | 9 +- src/core/shapes/mesh.cpp | 2 - 11 files changed, 210 insertions(+), 454 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e1961e..ef303bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() - +link_libraries(stdc++) find_package(Python3 REQUIRED) find_package(PythonLibs 3 REQUIRED) diff --git a/src/api/accelerator.h b/src/api/accelerator.h index 81ab8f5..ee3709a 100644 --- a/src/api/accelerator.h +++ b/src/api/accelerator.h @@ -28,9 +28,11 @@ namespace miyuki::core { class Scene; - class Accelerator { + class Accelerator : public Entity{ public: virtual void build(Scene &scene) = 0; + + virtual bool intersect(const Ray &ray, Intersection &isct) = 0; }; } diff --git a/src/api/mesh.h b/src/api/mesh.h index 02c3e7c..02e83e9 100644 --- a/src/api/mesh.h +++ b/src/api/mesh.h @@ -143,10 +143,9 @@ namespace miyuki::core { }; - class Mesh final : public Shape { + class Mesh final : public Entity { bool _loaded = false; public: - std::shared_ptr accelerator; std::vector triangles; VertexData _vertex_data; std::vector _indices; @@ -161,14 +160,6 @@ namespace miyuki::core { MYK_AUTO_INIT(filename, materials) - bool intersect(const Ray &ray, Intersection &isct) const override { - return accelerator->intersect(ray, isct); - } - - [[nodiscard]] Bounds3f getBoundingBox() const override { - return accelerator->getBoundingBox(); - } - // TODO: set import directory bool importFromFile(const std::string &filename); @@ -177,7 +168,7 @@ namespace miyuki::core { void fromBinary(const std::vector &buffer); - void foreach(const std::function &func) override; + void foreach(const std::function &func) ; bool loadFromFile(const std::string &filename); @@ -189,7 +180,7 @@ namespace miyuki::core { }; - class MeshInstance final : public Shape { + class MeshInstance final : public Entity { public: MYK_DECL_CLASS(MeshInstance, "MeshInstance", interface = "Shape") @@ -198,34 +189,7 @@ namespace miyuki::core { MYK_AUTO_SER(transform, mesh) - bool intersect(const Ray &ray, Intersection &isct) const override { - auto o = invTransform(ray.o); - auto p = invTransform(ray.o + ray.d); - Float k = (p - o).length(); - Ray transformedRay(o, (p - o).normalized(), k * ray.tMin, k * ray.tMax); - Intersection localIsct; - if (mesh->intersect(transformedRay, localIsct)) { - Float t = localIsct.distance / k; - if (t < isct.distance) { - isct = localIsct; - isct.distance = t; - isct.Ng = transform(isct.Ng); - isct.Ns = transform(isct.Ns); - isct.shape = localIsct.shape; - return true; - } - } - return false; - } - - [[nodiscard]] Bounds3f getBoundingBox() const override { - Bounds3f box; - box = box.unionOf(transform(mesh->getBoundingBox().pMin)); - box = box.unionOf(transform(mesh->getBoundingBox().pMax)); - return box; - } - - void foreach(const std::function &func) override { + void foreach(const std::function &func) { mesh->foreach(func); } diff --git a/src/api/scene.h b/src/api/scene.h index 7189860..042fe3b 100644 --- a/src/api/scene.h +++ b/src/api/scene.h @@ -35,11 +35,12 @@ namespace miyuki::core { class Scene { - std::shared_ptr accelerator; - std::atomic rayCounter = 0; + std::shared_ptr accelerator; + std::atomic rayCounter = 0; public: std::vector> lights; - std::vector> shapes; + std::vector> meshes; + std::vector> instances; bool intersect(const Ray &ray, Intersection &isct); diff --git a/src/core/accelerators/embree-backend.cpp b/src/core/accelerators/embree-backend.cpp index 4444c25..447399a 100644 --- a/src/core/accelerators/embree-backend.cpp +++ b/src/core/accelerators/embree-backend.cpp @@ -22,49 +22,30 @@ #include "embree-backend.h" #include -#ifdef MYK_USE_EMBREE - -namespace miyuki::core{ - void EmbreeAccelerator::build(const Mesh *mesh) { +#ifdef MYK_USE_EMBREE +namespace miyuki::core { + void miyuki::core::EmbreeAccelerator::build(miyuki::core::Scene &scene) { + MIYUKI_NOT_IMPLEMENTED(); } - bool EmbreeAccelerator::intersect(const Ray &ray, Intersection &isct) const { + bool miyuki::core::EmbreeAccelerator::intersect(const miyuki::core::Ray &ray, miyuki::core::Intersection &isct) { + MIYUKI_NOT_IMPLEMENTED(); return false; } - Bounds3f EmbreeAccelerator::getBoundingBox() const { - return miyuki::Bounds3f(); - } - - void EmbreeTopLevelAccelerator::build(const std::vector &vector) { - } - - bool EmbreeTopLevelAccelerator::intersect(const Ray &ray, Intersection &isct) const { - return false; - } - - Bounds3f EmbreeTopLevelAccelerator::getBoundingBox() const { - return miyuki::Bounds3f(); - } -} #else -namespace miyuki::core{ - - void EmbreeAccelerator::build(const Mesh *mesh) { + void miyuki::core::EmbreeAccelerator::build(miyuki::core::Scene &scene) { MIYUKI_NOT_IMPLEMENTED(); } - bool EmbreeAccelerator::intersect(const Ray &ray, Intersection &isct) const { + bool miyuki::core::EmbreeAccelerator::intersect(const miyuki::core::Ray &ray, miyuki::core::Intersection &isct) { MIYUKI_NOT_IMPLEMENTED(); - return false; } + return false; - Bounds3f EmbreeAccelerator::getBoundingBox() const { - MIYUKI_NOT_IMPLEMENTED(); - return miyuki::Bounds3f(); - } -} -#endif \ No newline at end of file + +#endif +} \ No newline at end of file diff --git a/src/core/accelerators/embree-backend.h b/src/core/accelerators/embree-backend.h index 0abdf76..2deb5cc 100644 --- a/src/core/accelerators/embree-backend.h +++ b/src/core/accelerators/embree-backend.h @@ -31,21 +31,11 @@ namespace miyuki::core { public: MYK_DECL_CLASS(EmbreeAccelerator, "EmbreeAccelerator", interface = "Accelerator") - void build(const Mesh *mesh) override; + void build(Scene &scene) override; - bool intersect(const Ray &ray, Intersection &isct) const override; + bool intersect(const Ray &ray, Intersection &isct) override; - Bounds3f getBoundingBox() const override; }; - class EmbreeTopLevelAccelerator final : public TopLevelAccelerator{ - public: - MYK_DECL_CLASS(EmbreeTopLevelAccelerator, "EmbreeTopLevelAccelerator", interface = "TopLevelAccelerator") - - void build(const std::vector &vector) override; - bool intersect(const Ray &ray, Intersection &isct) const override; - - Bounds3f getBoundingBox() const override; - }; } #endif //MIYUKIRENDERER_EMBREE_BACKEND_H diff --git a/src/core/accelerators/sahbvh.cpp b/src/core/accelerators/sahbvh.cpp index 8d30e29..4210841 100644 --- a/src/core/accelerators/sahbvh.cpp +++ b/src/core/accelerators/sahbvh.cpp @@ -23,257 +23,206 @@ #include #include "sahbvh.h" #include +#include +#include namespace miyuki::core { - int BVHAccelerator::recursiveBuild(int begin, int end, int depth) { - - // log::log("depth: {}, primitives:{} \n", depth, end - begin); - Bounds3f box{{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}; - Bounds3f centroidBound{{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}; - - - if (end == begin)return -1; - for (auto i = begin; i < end; i++) { - box = box.unionOf(primitive[i].getBoundingBox()); - centroidBound = centroidBound.unionOf(primitive[i].getBoundingBox().centroid()); - } - if (depth == 0) { - boundBox = box; - } - - if (end - begin <= 4 || depth >= 20) { - BVHNode node; - - node.box = box; - node.first = begin; - node.count = end - begin; - node.left = node.right = -1; - nodes.push_back(node); - return nodes.size() - 1; - } else { - - int axis = 0; - auto size = centroidBound.size(); - if (size.x > size.y) { - if (size.x > size.z) { - axis = 0; - } else { - axis = 2; - } - } else { - if (size.y > size.z) { - axis = 1; - } else { - axis = 2; - } + class BVHAccelerator::BVHAcceleratorInternal final { + struct BVHNode { + Bounds3f box; + uint32_t first = -1; + uint32_t count = -1; + int left = -1, right = -1; + + [[nodiscard]] bool isLeaf() const { + return left < 0 && right < 0; } - if (size[axis] == 0.0f) { - auto ret = nodes.size(); - nodes.emplace_back(); + }; - BVHNode &node = nodes.back(); - node.box = box; - node.count = -1; - auto mid = (begin + end) / 2; - nodes[ret].left = recursiveBuild(begin, mid, depth + 1); - nodes[ret].right = recursiveBuild(mid, end, depth + 1); + std::vector primitive; + std::vector nodes; - return ret; - } - constexpr size_t nBuckets = 12; - struct Bucket { - size_t count = 0; - Bounds3f bound; + Bounds3f boundBox; - Bucket() : bound({{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}) {} - }; - Bucket buckets[nBuckets]; - for (int i = begin; i < end; i++) { - auto offset = centroidBound.offset(primitive[i].getBoundingBox().centroid())[axis]; - int b = std::min(nBuckets - 1, std::floor(offset * nBuckets)); - buckets[b].count++; - buckets[b].bound = buckets[b].bound.unionOf(primitive[i].getBoundingBox()); - } - Float cost[nBuckets - 1] = {0}; - for (int i = 0; i < nBuckets - 1; i++) { - Bounds3f b0, b1; - int count0 = 0, count1 = 0; - for (int j = 0; j <= i; j++) { - b0 = b0.unionOf(buckets[j].bound); - count0 += buckets[j].count; + static Float intersectAABB(const Bounds3f &box, const Ray &ray, const Vec3f &invd) { + Vec3f t0 = (box.pMin - ray.o) * invd; + Vec3f t1 = (box.pMax - ray.o) * invd; + Vec3f tMin = min(t0, t1), tMax = max(t0, t1); + if (tMin.max() <= tMax.min()) { + auto t = std::max(ray.tMin + RayBias, tMin.max()); + if (t >= ray.tMax + RayBias) { + return -1; } - for (int j = i + 1; j < nBuckets; j++) { - b1 = b1.unionOf(buckets[j].bound); - count1 += buckets[j].count; - } - cost[i] = 0.125 + - (float(count0) * b0.surfaceArea() + float(count1) * b1.surfaceArea()) / box.surfaceArea(); + return t; } - int splitBuckets = 0; - Float minCost = cost[0]; - for (int i = 1; i < nBuckets - 1; i++) { - if (cost[i] <= minCost) { - minCost = cost[i]; - splitBuckets = i; - } - } - auto mid = std::partition(&primitive[begin], &primitive[end - 1] + 1, [&](MeshTriangle &p) { - int b = centroidBound.offset(p.getBoundingBox().centroid())[axis] * nBuckets; - if (b == nBuckets) { - b = nBuckets - 1; - } - return b <= splitBuckets; - }); - if (mid == &primitive[begin] || mid == &primitive[end - 1] + 1) { - log::log("empty split at {}, {}\n", depth, end - begin); - } - auto ret = nodes.size(); - nodes.emplace_back(); - - BVHNode &node = nodes.back(); - node.box = box; - node.count = -1; - nodes[ret].left = recursiveBuild(begin, mid - &primitive[0], depth + 1); - nodes[ret].right = recursiveBuild(mid - &primitive[0], end, depth + 1); - - return ret; + return -1; } - } - void BVHAccelerator::build(const Mesh *mesh) { - nodes.clear(); - log::log("Building BVH\n"); - primitive = mesh->triangles; - recursiveBuild(0, primitive.size(), 0); - log::log("BVH nodes:{}\n", nodes.size()); - } - - int TopLevelBVHAccelerator::recursiveBuild(int begin, int end, int depth) { - - // log::log("depth: {}, primitives:{} \n", depth, end - begin); - Bounds3f box{{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}; - Bounds3f centroidBound{{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}; + int recursiveBuild(int begin, int end, int depth) { +// log::log("depth: {}, primitives:{} \n", depth, end - begin); + Bounds3f box{{MaxFloat, MaxFloat, MaxFloat}, + {MinFloat, MinFloat, MinFloat}}; + Bounds3f centroidBound{{MaxFloat, MaxFloat, MaxFloat}, + {MinFloat, MinFloat, MinFloat}}; + if (depth == 0) { + boundBox = box; + } + if (end == begin)return -1; + for (auto i = begin; i < end; i++) { + box = box.unionOf(primitive[i].getBoundingBox()); + centroidBound = centroidBound.unionOf(primitive[i].getBoundingBox().centroid()); + } - if (end == begin)return -1; - for (auto i = begin; i < end; i++) { - box = box.unionOf(primitive[i]->getBoundingBox()); - centroidBound = centroidBound.unionOf(primitive[i]->getBoundingBox().centroid()); - } - if (depth == 0) { - boundBox = box; - } - if (end - begin <= 4 || depth >= 20) { - BVHNode node; + if (end - begin <= 4 || depth >= 20) { + BVHNode node; - node.box = box; - node.first = begin; - node.count = end - begin; - node.left = node.right = -1; - nodes.push_back(node); - return nodes.size() - 1; - } else { + node.box = box; + node.first = begin; + node.count = end - begin; + node.left = node.right = -1; + nodes.push_back(node); + return nodes.size() - 1; + } else { - int axis = 0; - auto size = centroidBound.size(); - if (size.x > size.y) { - if (size.x > size.z) { - axis = 0; + int axis = 0; + auto size = centroidBound.size(); + if (size.x > size.y) { + if (size.x > size.z) { + axis = 0; + } else { + axis = 2; + } } else { - axis = 2; + if (size.y > size.z) { + axis = 1; + } else { + axis = 2; + } } - } else { - if (size.y > size.z) { - axis = 1; - } else { - axis = 2; + constexpr size_t nBuckets = 12; + struct Bucket { + size_t count = 0; + Bounds3f bound; + + Bucket() : bound({{MaxFloat, MaxFloat, MaxFloat}, + {MinFloat, MinFloat, MinFloat}}) {} + }; + Bucket buckets[nBuckets]; + for (int i = begin; i < end; i++) { + auto offset = centroidBound.offset(primitive[i].getBoundingBox().centroid())[axis]; + int b = std::min(nBuckets - 1, std::floor(offset * nBuckets)); + buckets[b].count++; + buckets[b].bound = buckets[b].bound.unionOf(primitive[i].getBoundingBox()); } - } - if (size[axis] == 0.0f) { + Float cost[nBuckets - 1] = {0}; + for (int i = 0; i < nBuckets - 1; i++) { + Bounds3f b0, b1; + int count0 = 0, count1 = 0; + for (int j = 0; j <= i; j++) { + b0 = b0.unionOf(buckets[j].bound); + count0 += buckets[j].count; + } + for (int j = i + 1; j < nBuckets; j++) { + b1 = b1.unionOf(buckets[j].bound); + count1 += buckets[j].count; + } + cost[i] = 0.125 + (count0 * b0.surfaceArea() + count1 * b1.surfaceArea()) / box.surfaceArea(); + } + int splitBuckets = 0; + Float minCost = cost[0]; + for (int i = 1; i < nBuckets - 1; i++) { + if (cost[i] <= minCost) { + minCost = cost[i]; + splitBuckets = i; + } + } + auto mid = std::partition(&primitive[begin], &primitive[end - 1] + 1, [&](MeshTriangle &p) { + int b = centroidBound.offset(p.getBoundingBox().centroid())[axis] * nBuckets; + if (b == nBuckets) { + b = nBuckets - 1; + } + return b <= splitBuckets; + }); auto ret = nodes.size(); nodes.emplace_back(); BVHNode &node = nodes.back(); node.box = box; node.count = -1; - auto mid = (begin + end) / 2; - nodes[ret].left = recursiveBuild(begin, mid, depth + 1); - nodes[ret].right = recursiveBuild(mid, end, depth + 1); + nodes.push_back(node); + nodes[ret].left = recursiveBuild(begin, mid - &primitive[0], depth + 1); + nodes[ret].right = recursiveBuild(mid - &primitive[0], end, depth + 1); return ret; } - constexpr size_t nBuckets = 12; - struct Bucket { - size_t count = 0; - Bounds3f bound; + } - Bucket() : bound({{MaxFloat, MaxFloat, MaxFloat}, - {MinFloat, MinFloat, MinFloat}}) {} - }; - Bucket buckets[nBuckets]; - for (int i = begin; i < end; i++) { - auto offset = centroidBound.offset(primitive[i]->getBoundingBox().centroid())[axis]; - int b = std::min(nBuckets - 1, std::floor(offset * nBuckets)); - buckets[b].count++; - buckets[b].bound = buckets[b].bound.unionOf(primitive[i]->getBoundingBox()); - } - Float cost[nBuckets - 1] = {0}; - for (int i = 0; i < nBuckets - 1; i++) { - Bounds3f b0, b1; - int count0 = 0, count1 = 0; - for (int j = 0; j <= i; j++) { - b0 = b0.unionOf(buckets[j].bound); - count0 += buckets[j].count; - } - for (int j = i + 1; j < nBuckets; j++) { - b1 = b1.unionOf(buckets[j].bound); - count1 += buckets[j].count; - } - cost[i] = 0.125 + - (float(count0) * b0.surfaceArea() + float(count1) * b1.surfaceArea()) / box.surfaceArea(); - } - int splitBuckets = 0; - Float minCost = cost[0]; - for (int i = 1; i < nBuckets - 1; i++) { - if (cost[i] <= minCost) { - minCost = cost[i]; - splitBuckets = i; + public: + void build(const std::vector &primitives) { + nodes.clear(); + primitive = primitives; + recursiveBuild(0, primitive.size(), 0); + log::log("BVH nodes:{}\n", nodes.size()); + } + + bool intersect(const Ray &ray, Intersection &isct) const { + bool hit = false; + auto invd = Vec3f(1) / ray.d; + constexpr int maxDepth = 40; + const BVHNode *stack[maxDepth]; + int sp = 0; + stack[sp++] = &nodes[0]; + while (sp > 0) { + auto p = stack[--sp]; + auto t = intersectAABB(p->box, ray, invd); + + if (t < 0 || t > isct.distance) { + continue; } - } - auto mid = std::partition(&primitive[begin], &primitive[end - 1] + 1, [&](Shape *p) { - int b = centroidBound.offset(p->getBoundingBox().centroid())[axis] * nBuckets; - if (b == nBuckets) { - b = nBuckets - 1; + if (p->isLeaf()) { + for (int i = p->first; i < p->first + p->count; i++) { + if (primitive[i].intersect(ray, isct)) { + hit = true; + } + } + } else { + if (p->left >= 0) + stack[sp++] = &nodes[p->left]; + if (p->right >= 0) + stack[sp++] = &nodes[p->right]; } - return b <= splitBuckets; - }); - if (mid == &primitive[begin] || mid == &primitive[end - 1] + 1) { - log::log("empty split at {}, {}\n", depth, end - begin); } - auto ret = nodes.size(); - nodes.emplace_back(); + return hit; + } + - BVHNode &node = nodes.back(); - node.box = box; - node.count = -1; - nodes[ret].left = recursiveBuild(begin, mid - &primitive[0], depth + 1); - nodes[ret].right = recursiveBuild(mid - &primitive[0], end, depth + 1); + [[nodiscard]] Bounds3f getBoundingBox() const { + return boundBox; + } + }; - return ret; + void BVHAccelerator::build(Scene &scene) { + for (const auto &i: scene.meshes) { + auto node = new BVHAcceleratorInternal(); + node->build(i->triangles); + internal.emplace_back(node); } } - void TopLevelBVHAccelerator::build(const std::vector &primitives) { - nodes.clear(); - log::log("Building BVH\n"); - primitive = primitives; - recursiveBuild(0, primitive.size(), 0); - log::log("BVH nodes:{}\n", nodes.size()); + bool BVHAccelerator::intersect(const Ray &ray, Intersection &isct) { + bool hit = false; + for (auto i : internal) { + if (i->intersect(ray, isct)) + hit = true; + } + return hit; + } + + BVHAccelerator::~BVHAccelerator() { + for (auto i: internal) { + delete i; + } } } \ No newline at end of file diff --git a/src/core/accelerators/sahbvh.h b/src/core/accelerators/sahbvh.h index fc4061b..cf22ee4 100644 --- a/src/core/accelerators/sahbvh.h +++ b/src/core/accelerators/sahbvh.h @@ -29,153 +29,19 @@ namespace miyuki::core { - class BVHAccelerator final : public Accelerator { - struct BVHNode { - Bounds3f box; - uint32_t first = -1; - uint32_t count = -1; - int left = -1, right = -1; - - [[nodiscard]] bool isLeaf() const { - return left < 0 && right < 0; - } - }; - - std::vector primitive; - std::vector nodes; - - Bounds3f boundBox; - - static Float intersectAABB(const Bounds3f &box, const Ray &ray, const Vec3f &invd) { - Vec3f t0 = (box.pMin - ray.o) * invd; - Vec3f t1 = (box.pMax - ray.o) * invd; - Vec3f tMin = min(t0, t1), tMax = max(t0, t1); - if (tMin.max() <= tMax.min()) { - auto t = std::max(ray.tMin + RayBias, tMin.max()); - if (t >= ray.tMax + RayBias) { - return -1; - } - return t; - } - return -1; - } - - int recursiveBuild(int begin, int end, int depth); - - public: - MYK_DECL_CLASS(BVHAccelerator, "BVHAccelerator", interface = "Acclerator") - - [[nodiscard]] Bounds3f getBoundingBox() const override { - return boundBox; - } - - - - void build(const Mesh *mesh) override; - bool intersect(const Ray &ray, Intersection &isct) const override { - bool hit = false; - auto invd = Vec3f(1) / ray.d; - constexpr int maxDepth = 40; - const BVHNode *stack[maxDepth]; - int sp = 0; - stack[sp++] = &nodes[0]; - while (sp > 0) { - auto p = stack[--sp]; - auto t = intersectAABB(p->box, ray, invd); - - if (t < 0 || t > isct.distance) { - continue; - } - if (p->isLeaf()) { - for (int i = p->first; i < p->first + p->count; i++) { - if (primitive[i].intersect(ray, isct)) { - hit = true; - } - } - } else { - if (p->left >= 0) - stack[sp++] = &nodes[p->left]; - if (p->right >= 0) - stack[sp++] = &nodes[p->right]; - } - } - return hit; - } - }; - - class TopLevelBVHAccelerator final : public TopLevelAccelerator { - struct BVHNode { - Bounds3f box; - uint32_t first = -1; - uint32_t count = -1; - int left = -1, right = -1; - - [[nodiscard]] bool isLeaf() const { - return left < 0 && right < 0; - } - }; - - std::vector primitive; - std::vector nodes; - - Bounds3f boundBox; - - static Float intersectAABB(const Bounds3f &box, const Ray &ray, const Vec3f &invd) { - Vec3f t0 = (box.pMin - ray.o) * invd; - Vec3f t1 = (box.pMax - ray.o) * invd; - Vec3f tMin = min(t0, t1), tMax = max(t0, t1); - if (tMin.max() <= tMax.min()) { - auto t = std::max(ray.tMin + RayBias, tMin.max()); - if (t >= ray.tMax + RayBias) { - return -1; - } - return t; - } - return -1; - } - - int recursiveBuild(int begin, int end, int depth); + class BVHAccelerator final : public Accelerator { + class BVHAcceleratorInternal; + std::vector internal; public: - MYK_DECL_CLASS(TopLevelBVHAccelerator, "TopLevelBVHAccelerator", interface = "TopLevelAcclerator") - - [[nodiscard]] Bounds3f getBoundingBox() const override { - return boundBox; - } - + MYK_DECL_CLASS(BVHAccelerator, "BVHAccelerator", interface = "BVHAccelerator") - void build(const std::vector &primitives) override; + void build(Scene &scene) override; - bool intersect(const Ray &ray, Intersection &isct) const override { - bool hit = false; - auto invd = Vec3f(1) / ray.d; - constexpr int maxDepth = 40; - const BVHNode *stack[maxDepth]; - int sp = 0; - stack[sp++] = &nodes[0]; - while (sp > 0) { - auto p = stack[--sp]; - auto t = intersectAABB(p->box, ray, invd); + bool intersect(const Ray &ray, Intersection &isct) override; - if (t < 0 || t > isct.distance) { - continue; - } - if (p->isLeaf()) { - for (int i = p->first; i < p->first + p->count; i++) { - if (primitive[i]->intersect(ray, isct)) { - hit = true; - } - } - } else { - if (p->left >= 0) - stack[sp++] = &nodes[p->left]; - if (p->right >= 0) - stack[sp++] = &nodes[p->right]; - } - } - return hit; - } + ~BVHAccelerator(); }; } #endif //MIYUKIRENDERER_SAHBVH_H diff --git a/src/core/graph.cpp b/src/core/graph.cpp index 6950781..17570da 100644 --- a/src/core/graph.cpp +++ b/src/core/graph.cpp @@ -15,8 +15,14 @@ namespace miyuki::core { sampler->preprocess(); Film film(filmDimension[0], filmDimension[1]); auto scene = std::make_shared(); - for (const auto& i: shapes) { - scene->shapes.emplace_back(i); + for (const auto &i: shapes) { + if (auto mesh = std::dynamic_pointer_cast(i)) { + scene->meshes.emplace_back(mesh); + } else if (auto instance = std::dynamic_pointer_cast(i)) { + scene->instances.emplace_back(instance); + } else { + MIYUKI_THROW(std::runtime_error, "Unknown shape type"); + } } scene->preprocess(); log::log("Start Rendering...\n"); diff --git a/src/core/scene.cpp b/src/core/scene.cpp index 0ebe949..813ea17 100644 --- a/src/core/scene.cpp +++ b/src/core/scene.cpp @@ -23,11 +23,12 @@ #include #include #include +#include namespace miyuki::core { void Scene::preprocess() { - accelerator = std::make_shared(); + accelerator = std::make_shared(); auto setLight = [=](MeshTriangle *triangle) { auto mat = triangle->getMaterial(); if (mat && mat->emission != nullptr) { @@ -36,13 +37,11 @@ namespace miyuki::core { lights.emplace_back(light); } }; - std::vector v; - for (auto &i:shapes) { + for (auto &i:meshes) { i->preprocess(); - v.push_back(i.get()); i->foreach(setLight); } - accelerator->build(v); + accelerator->build(*this); } bool Scene::intersect(const miyuki::core::Ray &ray, miyuki::core::Intersection &isct) { diff --git a/src/core/shapes/mesh.cpp b/src/core/shapes/mesh.cpp index be96b10..c043786 100644 --- a/src/core/shapes/mesh.cpp +++ b/src/core/shapes/mesh.cpp @@ -90,8 +90,6 @@ namespace miyuki::core { _materials.emplace_back(nullptr); } } - accelerator = std::dynamic_pointer_cast(CreateEntity("BVHAccelerator")); - accelerator->build(this); } bool Mesh::importFromFile(const std::string &filename) {