diff --git a/source/include/worldoptimiser.h b/source/include/worldoptimiser.h index 4abac67..8404ef0 100644 --- a/source/include/worldoptimiser.h +++ b/source/include/worldoptimiser.h @@ -34,6 +34,8 @@ public: class BVHOptimisation : public WorldOptimiser { +private: + void makeTree(Group *leaf, int depth = 0); public: void run(); }; diff --git a/source/worldoptimiser/bvhoptimisation.cpp b/source/worldoptimiser/bvhoptimisation.cpp new file mode 100644 index 0000000..6242723 --- /dev/null +++ b/source/worldoptimiser/bvhoptimisation.cpp @@ -0,0 +1,145 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * BVH world optimiser implementation + * + * Created by Manoƫl Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#include +#include +#include + +void BVHOptimisation::makeTree(Group *leaf, int depth) +{ + /* Let's take the bounding box of the root */ + BoundingBox rootBB = leaf->getBounds(); + + double dx = (rootBB.max.x - rootBB.min.x); + double dy = (rootBB.max.y - rootBB.min.y); + double dz = (rootBB.max.z - rootBB.min.z); + /* Take the mid value for each axes */ + Tuple midMin = rootBB.min; + Tuple midMax = rootBB.max; + + BoundingBox SlicesBB[2]; + int sliceIdx; + Group *Slices[2]; + + double largestSide = max3(dx, dy, dz); + + int i; + + if (largestSide == dx) + { + midMin.x = rootBB.min.x + dx / 2.0; + midMax.x = rootBB.min.x + dx / 2.0; + } + else if (largestSide == dy) + { + midMin.y = rootBB.min.y + dy / 2.0; + midMax.y = rootBB.min.y + dy / 2.0; + } + else + { + midMin.z = rootBB.min.z + dx / 2.0; + midMax.z = rootBB.min.z + dx / 2.0; + } + + + /* Split the main bounding box into 8 boxes */ + SlicesBB[0] | rootBB.min; + SlicesBB[0] | midMax; + + SlicesBB[1] | rootBB.max; + SlicesBB[1] | midMin; + + + for (sliceIdx = 0 ; sliceIdx < 2 ; sliceIdx++) + { + Slices[sliceIdx] = nullptr; + } + + for (i = 0 ; i < leaf->getObjectCount(); i++) + { + Shape *shp = leaf->getObject(i); + if ((shp->getType() != Shape::GROUP) && (shp->getType() != Shape::OBJFILE)) + { + BoundingBox objBB = shp->getBounds(); + + for (sliceIdx = 0 ; sliceIdx < 2 ; sliceIdx++) + { + if (SlicesBB[sliceIdx].fitsIn(objBB)) + { + if (Slices[sliceIdx] == nullptr) + { + char name[32]; + snprintf(name, 32, "%d_Slice %d", depth, sliceIdx); + //for(int j=0; j < depth; j++) { printf(" "); } + //printf("%s\n", name); + Slices[sliceIdx] = new Group(name); + + Slices[sliceIdx]->setBounds(SlicesBB[sliceIdx]); + } + + Slices[sliceIdx]->addObject(shp); + leaf->removeObject(shp); + + i -= 1; + break; + } + } + } + else + { + leaf->removeObject(shp); + i -= 1; + } + } + + /* Now add the quadrant to the root and recurse in it */ + for (sliceIdx = 0 ; sliceIdx < 2 ; sliceIdx++) + { + if (Slices[sliceIdx] != nullptr) + { + this->makeTree(Slices[sliceIdx], depth + 1); + + Slices[sliceIdx]->updateBoundingBox(); + + leaf->addObject(Slices[sliceIdx]); +#if 0 + Cube *cb = new Cube(); + double sx = SlicesBB[sliceIdx].max.x - SlicesBB[sliceIdx].min.x; + double sy = SlicesBB[sliceIdx].max.y - SlicesBB[sliceIdx].min.y; + double sz = SlicesBB[sliceIdx].max.z - SlicesBB[sliceIdx].min.z; + + cb->setTransform(translation(SlicesBB[sliceIdx].min.x, SlicesBB[sliceIdx].min.y, + SlicesBB[sliceIdx].min.z) * scaling(sx, sy, sz)); + cb->material.colour = Colour(0.01, 0.01, 0); + cb->materialSet = true; + cb->dropShadow = false; + cb->material.ambient = 0.1; + cb->material.reflective = 0; + cb->material.transparency = 0.95; + cb->material.refractiveIndex = 1; + cb->material.specular = 0; + leaf->addObject(cb); + + printf("%s: %d objs\n", Slices[sliceIdx]->getName(), + Slices[sliceIdx]->getObjectCount()); +#endif + } + } +} + +void BVHOptimisation::run() +{ + /* First let's clear our hands */ + this->moveInfiniteObjects(); + + /* Then let's have some fun! */ + this->moveAllObjects(); + + /* Now.. The fun start ! */ + makeTree(this->root, 0); +} \ No newline at end of file diff --git a/tests/ch12_test.cpp b/tests/ch12_test.cpp index 136bb2a..f7b8c6d 100644 --- a/tests/ch12_test.cpp +++ b/tests/ch12_test.cpp @@ -24,6 +24,8 @@ #include +#include + int main() { World w = World(); @@ -198,6 +200,9 @@ int main() /* ----------------------------- */ + BVHOptimisation opt; + w.finalise(opt); + /* Set the camera */ Camera camera = Camera(400, 200, 0.785); camera.setTransform(viewTransform(Point(8, 6, -8), diff --git a/tests/ch15_teapot_objfile.cpp b/tests/ch15_teapot_objfile.cpp index afabeba..6555f6b 100644 --- a/tests/ch15_teapot_objfile.cpp +++ b/tests/ch15_teapot_objfile.cpp @@ -89,6 +89,9 @@ int main() /* ----------------------------- */ + BVHOptimisation opt; + w.finalise(opt); + /* Set the camera */ Camera camera = Camera(80, 40, M_PI/2); camera.setTransform(viewTransform(Point(0, 7, 13),