#pragma once #include #include "../lib/mathlib.h" #include "../scene/object.h" #include "trace.h" #include "bvh.h" #include "list.h" #include "shapes.h" #include "tri_mesh.h" namespace PT { class Object { public: Object(Shape&& shape, Scene_ID id, unsigned int m = 0, const Mat4& T = Mat4::I) : trans(T), itrans(T.inverse()), _id(id), material(m), underlying(std::move(shape)) { has_trans = trans != Mat4::I; } Object(Tri_Mesh&& tri_mesh, Scene_ID id, unsigned int m = 0, const Mat4& T = Mat4::I) : trans(T), itrans(T.inverse()), _id(id), material(m), underlying(std::move(tri_mesh)) { has_trans = trans != Mat4::I; } Object(List&& list, Scene_ID id, unsigned int m = 0, const Mat4& T = Mat4::I) : trans(T), itrans(T.inverse()), _id(id), material(m), underlying(std::move(list)) { has_trans = trans != Mat4::I; } Object(BVH&& bvh, Scene_ID id, unsigned int m = 0, const Mat4& T = Mat4::I) : trans(T), itrans(T.inverse()), _id(id), material(m), underlying(std::move(bvh)) { has_trans = trans != Mat4::I; } Object(const Object& src) = delete; Object& operator=(const Object& src) = delete; Object& operator=(Object&& src) = default; Object(Object&& src) = default; BBox bbox() const { BBox box = std::visit(overloaded { [](const auto& o) { return o.bbox(); } }, underlying); if(has_trans) box.transform(trans); return box; } Trace hit(Ray ray) const { if(has_trans) ray.transform(itrans); Trace ret = std::visit(overloaded { [&ray](const auto& o) { return o.hit(ray); } }, underlying); if(ret.hit) { ret.material = material; if(has_trans) ret.transform(trans, itrans.T()); } return ret; } size_t visualize(GL::Lines& lines, GL::Lines& active, size_t level, const Mat4& vtrans) const { Mat4 next = has_trans ? vtrans * trans : vtrans; return std::visit(overloaded { [&](const BVH& bvh) { return bvh.visualize(lines, active, level, next); }, [&](const Tri_Mesh& mesh) { return mesh.visualize(lines, active, level, next); }, [](const auto&) { return size_t(0); } }, underlying); } Scene_ID id() const { return _id; } void set_trans(const Mat4& T) { trans = T; itrans = T.inverse(); has_trans = trans != Mat4::I; } private: bool has_trans; Mat4 trans, itrans; unsigned int material; Scene_ID _id; std::variant, List> underlying; }; }