diff --git a/CMakeLists.txt b/CMakeLists.txt index 48a0af5..c13aa74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,9 @@ add_executable(tracey_ex4 ex4.cpp) target_link_libraries(tracey_ex4 tracey) +add_executable(tracey_ex5 ex5.cpp) +target_link_libraries(tracey_ex5 tracey) + diff --git a/ex5.cpp b/ex5.cpp new file mode 100644 index 0000000..a2ede32 --- /dev/null +++ b/ex5.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include "camera/perspectivecamera.h" + +#include "scene/fastscene.h" + +#include "renderer/kdtreerenderer.h" +#include "renderer/simplerenderer.h" + +#include "shader/cooktorranceshader.h" + +#include "light/ambientlight.h" +#include "light/pointlight.h" +#include "light/spotlight.h" + +#include "primitive/objmodel.h" + +int main() { + FastScene scene; + scene.setEnvironmentMap(std::make_shared("data/space.png")); + + // Set up the camera + PerspectiveCamera camera; + camera.setFovAngle(90.0f); + camera.setPosition(Vector3d(0.0f, -2.5f, 10.0f)); + camera.setForwardDirection(Vector3d(0.0f, 0.6f, -1.0f)); + camera.setUpDirection(Vector3d(0.0f, 1.0f, 0.0f)); + + // Add shaders + auto redCook = std::make_shared(Color(1.0f, 0.0f, 0.0f), Color(1.0f, 1.0f, 1.0f), 1.0f, 0.3f); + auto goldCook = std::make_shared(Color(0.83f, 0.69f, 0.22f), Color(1.0f, 1.0f, 0.0f), 1.2f, 0.2f); + + scene.addObj("data/teapot_stadium.obj", Vector3d(1.0f, 1.0f, 1.0f) * 40.0f, Vector3d(-0.25f, -0.5f, -2.5f), goldCook); + scene.addObj("data/stadium.obj", Vector3d(1.0f, 1.0f, 1.0f) * 70.0f, Vector3d(-0.5f, -1.0f, -3.0f), redCook); + + // Add lights + scene.add(std::make_shared(0.1f)); + scene.add(std::make_shared(Vector3d(-0.25f, 20.0f, -3.0f), 60.0f)); + scene.add( + std::make_shared(Vector3d(-0.25f, 7.0f, -4.0f), Vector3d(0.0f, -1.0f, 0.0f), 10.0f, 30.0f, 25.0f)); + + // build the tree + scene.buildTree(); + + // Render the scene + SimpleRenderer renderer; + renderer.renderImage(scene, camera, 1920, 1080).save("result.png"); + + KDTreeRenderer kd_renderer; + kd_renderer.renderKDTree(scene, camera, 1920, 1080).save("result_kd.png"); + + return 0; +} diff --git a/renderer/kdtreerenderer.cpp b/renderer/kdtreerenderer.cpp new file mode 100644 index 0000000..b4ae141 --- /dev/null +++ b/renderer/kdtreerenderer.cpp @@ -0,0 +1,18 @@ +#include "camera/camera.h" +#include "renderer/kdtreerenderer.h" +#include "scene/fastscene.h" +#include + +Texture KDTreeRenderer::renderImage(Scene const &scene, Camera const &camera, int width, int height) { + Texture image(width, height); + std::cout << "KD Tree renderer will only output KD Tree visualization" << std::endl; + return image; +} + +Texture KDTreeRenderer::renderKDTree(FastScene const &scene, Camera const &camera, int width, int height) { + Texture image(width, height); + + // IMPLEMENT ME + + return image; +} \ No newline at end of file diff --git a/renderer/kdtreerenderer.h b/renderer/kdtreerenderer.h new file mode 100644 index 0000000..9a1a15c --- /dev/null +++ b/renderer/kdtreerenderer.h @@ -0,0 +1,22 @@ +#ifndef KDTREERENDERER_H +#define KDTREERENDERER_H + +#include "renderer/renderer.h" + +// Forward Declaration +class FastScene; + +class KDTreeRenderer : public Renderer { + +public: + // Constructor / Destructor + KDTreeRenderer() = default; + ~KDTreeRenderer() override = default; + + // Render functions + Texture renderImage(Scene const &scene, Camera const &camera, int width, int height) override; + + Texture renderKDTree(FastScene const &scene, Camera const &camera, int width, int height); +}; + +#endif \ No newline at end of file diff --git a/scene/fastscene.cpp b/scene/fastscene.cpp new file mode 100644 index 0000000..158ee4c --- /dev/null +++ b/scene/fastscene.cpp @@ -0,0 +1,73 @@ +#include "primitive/primitive.h" +#include "scene/fastscene.h" +#include "shader/shader.h" +#include +#include + +int Node::countNodeIntersections(const Ray &ray, float t0, float t1) const { + // IMPLEMENT ME + return 0; +} + +bool Node::findIntersection(Ray &ray, float t0, float t1) const { + // IMPLEMENT ME + // If this is a leaf node, we intersect with all the primitives... + // ... otherwise we continue through the branches + // Determine the order in which we intersect the child nodes + // Traverse the necessary children + return false; +} + +bool Node::findOcclusion(Ray &ray, float t0, float t1) const { + // IMPLEMENT ME + return false; +} + +int FastScene::countNodeIntersections(const Ray &ray) const { + // IMPLEMENT ME + return false; +} + +bool FastScene::findIntersection(Ray &ray) const { + // IMPLEMENT ME + return false; +} + +bool FastScene::findOcclusion(Ray &ray) const { + // IMPLEMENT ME + return false; +} + +void FastScene::buildTree(int maximumDepth, int minimumNumberOfPrimitives) { + // IMPLEMENT ME + // Set the new depth and number of primitives + + // Determine the bounding box of the kD-Tree + + // Recursively build the kD-Tree +} + +std::unique_ptr FastScene::build(Vector3d const &minimumBounds, Vector3d const &maximumBounds, const std::vector> &primitives, int depth) { + // IMPLEMENT ME + // Determine the diameter of the bounding box + + // Test whether we have reached a leaf node... + + // ... otherwise create a new inner node by splitting through the widest + // dimension + + // Determine the split position + // Note: Use the median of the minimum bounds of the primitives + + // Divide primitives into the left and right lists + // Remember: A primitive can be in both lists! + // Also remember: You split exactly at the minimum of a primitive, + // make sure *that* primitive does *not* appear in both lists! + + // Print out the number of primitives in the left and right child node + + // Set the left and right split vectors + + // Recursively build the tree + return nullptr; +} diff --git a/scene/fastscene.h b/scene/fastscene.h new file mode 100644 index 0000000..fd59324 --- /dev/null +++ b/scene/fastscene.h @@ -0,0 +1,46 @@ +#ifndef FASTSCENE_H +#define FASTSCENE_H + +#include "scene/scene.h" + +struct Node { + // Constructor / Destructor + Node() : dimension(0), split(0) {} + + // Traversal function + bool findIntersection(Ray &ray, float t0, float t1) const; + bool findOcclusion(Ray &ray, float t0, float t1) const; + int countNodeIntersections(const Ray &ray, float t0, float t1) const; + inline bool isLeaf() const { return (!this->primitives.empty() || (!this->child[0] && !this->child[1])); } + + // Branch split + std::unique_ptr child[2]; + int dimension; + float split; + + // Leaf primitives + std::vector> primitives; +}; + +class FastScene : public Scene { + +public: + // Raytracing functions + bool findIntersection(Ray &ray) const override; + bool findOcclusion(Ray &ray) const override; + int countNodeIntersections(const Ray &ray) const; + + // Setup functions + void buildTree(int maximumDepth = 10, int minimumNumberOfPrimitives = 2); + +private: + std::unique_ptr build(Vector3d const &minimumBounds, Vector3d const &maximumBounds, + const std::vector> &primitives, int depth); + + std::unique_ptr root; + int maximumDepth; + int minimumNumberOfPrimitives; + Vector3d absoluteMinimum, absoluteMaximum; +}; + +#endif