diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2024-05-16 08:03:42 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2024-05-16 08:03:42 -0400 |
commit | fdc2d91285cd9548a3c95f1bdfb75c70ccfffff6 (patch) | |
tree | 65e460dccf3336228d8b0803e334c9ab2f4bf582 | |
parent | 549fe1388c9dd641c698d4a2ea0a1e6f754df534 (diff) |
abstract objects
-rw-r--r-- | main.cpp | 30 | ||||
-rw-r--r-- | object.h | 32 | ||||
-rw-r--r-- | sphere.h | 20 | ||||
-rw-r--r-- | world.h | 14 |
4 files changed, 62 insertions, 34 deletions
@@ -3,9 +3,9 @@ constexpr double Aspect = 16.0 / 9.0; constexpr unsigned Height = Width / Aspect; #include "color.h" +#include "object.h" #include "ray.h" #include "renderer.h" -#include "sphere.h" #include "vec3.h" #include "view.h" #include "world.h" @@ -36,7 +36,7 @@ static std::chrono::duration<double> renderTime; static color ray_color(const ray& r, int depth = 50); static void initiateRender(SDL_Surface *canvas); -static void showObjectControls(int index, Sphere& o); +static void showObjectControls(int index, std::unique_ptr<Object>& o); static void addRandomObject(); static void preview(SDL_Surface *canvas); @@ -52,7 +52,7 @@ int main() ImGui_ImplSDL2_InitForSDLRenderer(window, painter); ImGui_ImplSDLRenderer2_Init(painter); - world.add(point3(0.00, -100.50, -1.0), 100.0, + world.add<Sphere>(point3(0.00, -100.50, -1.0), 100.0, Material::Lambertian, color(0.5, 1.0, 0.5)); for (auto i : std::views::iota(0, 10)) addRandomObject(); @@ -173,8 +173,8 @@ color ray_color(const ray& r, int depth) return {}; if (auto hit = world.hit(r); hit) { - const auto& [closest, sphere] = *hit; - const auto [atten, scat] = sphere.scatter(r, closest); + const auto& [closest, object] = *hit; + const auto [atten, scat] = object->scatter(r, closest); return atten * ray_color(scat, depth - 1); } else { const auto unitDir = r.direction().normalize(); @@ -202,25 +202,25 @@ void initiateRender(SDL_Surface *canvas) (uint32_t *)canvas->pixels)); } -void showObjectControls(int index, Sphere& o) +void showObjectControls(int index, std::unique_ptr<Object>& o) { const auto idx = std::to_string(index); ImGui::SetNextItemWidth(200); - ImGui::Combo((std::string("mat") + idx).c_str(), reinterpret_cast<int *>(&o.M), - "Lambertian\0Metal\0Dielectric\0"); - ImGui::SameLine(); ImGui::SetNextItemWidth(100); - ImGui::InputDouble((std::string("radius") + idx).c_str(), - &o.radius, 0.1, 0.05, "%.2lf"); + ImGui::Combo((std::string("mat") + idx).c_str(), + reinterpret_cast<int *>(&o->M), "Lambertian\0Metal\0Dielectric\0"); + //ImGui::SameLine(); ImGui::SetNextItemWidth(100); + //ImGui::InputDouble((std::string("radius") + idx).c_str(), + // &o->radius, 0.1, 0.05, "%.2lf"); ImGui::SetNextItemWidth(100); ImGui::InputDouble((std::string("x") + idx).c_str(), - &o.center.x(), 0.05, 0.05, "%.2lf"); + &o->center.x(), 0.05, 0.05, "%.2lf"); ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble((std::string("y") + idx).c_str(), - &o.center.y(), 0.1, 0.05, "%.2lf"); + &o->center.y(), 0.1, 0.05, "%.2lf"); ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble((std::string("z") + idx).c_str(), - &o.center.z(), 0.1, 0.05, "%.2lf"); + &o->center.z(), 0.1, 0.05, "%.2lf"); } void addRandomObject() @@ -228,7 +228,7 @@ void addRandomObject() const point3 pos = vec3::random() * vec3(6, 0.8, 3) - vec3(3, 0, 3.8); const color col = vec3::random(); const auto mat = (int)(randomN() * (int)Material::Undefined); - world.add(pos, randomN() * 0.3 + 0.05, (Material)mat, col); + world.add<Sphere>(pos, randomN() * 0.3 + 0.05, (Material)mat, col); } void preview(SDL_Surface *canvas) diff --git a/object.h b/object.h new file mode 100644 index 0000000..5db620e --- /dev/null +++ b/object.h @@ -0,0 +1,32 @@ +#ifndef OBJECT_H +#define OBJECT_H + +#include "color.h" +#include "ray.h" +#include "vec3.h" + +#include <optional> +#include <tuple> + +enum class Material : int { + Lambertian = 0, + Metal, + Dielectric, + Undefined +}; + +struct Object +{ + point3 center; + Material M; + color tint; + + Object(point3 center_, Material M_, color tint_): + center(center_), M(M_), tint(tint_) {} + + virtual std::pair<color, ray> scatter(const ray& r, double root) const = 0; + virtual std::optional<double> hit(const ray& r, double tmin, double tmax) const = 0; +}; + +#endif // OBJECT_H + @@ -2,6 +2,7 @@ #define SPHERE_H #include "color.h" +#include "object.h" #include "ray.h" #include "vec3.h" @@ -9,21 +10,14 @@ #include <optional> #include <tuple> -enum class Material : int { - Lambertian = 0, - Metal, - Dielectric, - Undefined -}; - -struct Sphere +struct Sphere : public Object { - point3 center; double radius; - Material M; - color tint; - std::pair<color, ray> scatter(const ray& r, double root) const { + Sphere(point3 center_, double radius_, Material M_, color tint_): + Object(center_, M_, tint_), radius(radius_) {} + + std::pair<color, ray> scatter(const ray& r, double root) const override { const auto p = r.at(root); auto normal = (p - center) / radius; @@ -52,7 +46,7 @@ struct Sphere } } - std::optional<double> hit(const ray& r, double tmin, double tmax) const { + std::optional<double> hit(const ray& r, double tmin, double tmax) const override { const vec3 oc = center - r.origin(); const auto a = r.direction().length_squared(); const auto h = r.direction().dot(oc); @@ -4,26 +4,28 @@ #include "sphere.h" #include <limits> +#include <memory> #include <optional> #include <tuple> #include <vector> struct World { - std::vector<Sphere> objects; + std::vector<std::unique_ptr<Object>> objects; + template<class T> void add(auto&&... args) { - objects.emplace_back(args...); + objects.emplace_back(new T(args...)); } - std::optional<std::pair<double, Sphere>> hit(const ray& r) const { + std::optional<std::pair<double, Object *>> hit(const ray& r) const { double closest = std::numeric_limits<double>::infinity(); - Sphere sphere; + Object *sphere; for (const auto& o : objects) { - if (auto t = o.hit(r, 0.001, closest); t) { + if (auto t = o->hit(r, 0.001, closest); t) { closest = *t; - sphere = o; + sphere = o.get(); } } |