/* * Created by Brett Terpstra 6920201 on 18/10/22. * Copyright (c) 2022 Brett Terpstra. All Rights Reserved. */ #ifndef STEP_2_TYPES_H #define STEP_2_TYPES_H #include #include #include // there were some files which needed access to these types // but including them from world.h would've resulted in circular includes, // so I moved them here. namespace Raytracing { struct HitData { // all the other values only matter if this is true bool hit{false}; // the hit point on the object Vec4 hitPoint{}; // the normal of that hit point Vec4 normal{}; // the length of the vector from its origin in its direction. PRECISION_TYPE length{0}; }; struct ScatterResults { // returns true to recast the ray with the provided ray bool scattered; // the new ray to be cast if scattered Ray newRay; // the color of the material Vec4 attenuationColor; }; // triangle type for model loading struct Triangle { public: Vec4 vertex1, vertex2, vertex3; bool hasNormals = false; Vec4 normal1, normal2, normal3; Vec4 uv1, uv2, uv3; AABB aabb; Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3): vertex1(v1), vertex2(v2), vertex3(v3) {} Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3, const Vec4& n1, const Vec4& n2, const Vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3), hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {} Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3, const Vec4& uv1, const Vec4& uv2, const Vec4& uv3, const Vec4& n1, const Vec4& n2, const Vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3), uv1(uv1), uv2(uv2), uv3(uv3), hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {} // slow method, not really required as all normals should be equal [[nodiscard]] Vec4 findClosestNormal(const Vec4& point) const { // no need to sqrt as exact distance doesn't matter auto n1Dist = (point - normal1).lengthSquared(); auto n2Dist = (point - normal2).lengthSquared(); auto n3Dist = (point - normal3).lengthSquared(); return (n1Dist < n2Dist && n1Dist < n3Dist) ? normal1 : (n2Dist < n3Dist ? normal2 : normal3); } }; // face type for model loading struct face { int v1, v2, v3; int uv1, uv2, uv3; int n1, n2, n3; }; class Material { protected: // most materials will need an albedo Vec4 baseColor; public: explicit Material(const Vec4& baseColor): baseColor(baseColor) {} // returns true if the ray was scattered along with the scattered ray, otherwise will return false with empty ray. // the returned vec4 is the attenuation color [[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const = 0; [[nodiscard]] Vec4 getBaseColor() const { return baseColor; } virtual ~Material() = default; }; class Object { protected: AABB aabb; Vec4 position; Material* material; public: Object(Material* material, const Vec4& position): material(material), position(position), aabb({}) {}; // return true if the ray intersects with this object, only between min and max [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const = 0; [[nodiscard]] Material* getMaterial() const { return material; } virtual Object* clone() = 0; virtual AABB& getAABB() { return aabb; } virtual void setAABB(const AABB& ab) { this->aabb = ab; } [[nodiscard]] Vec4 getPosition() const { return position; } virtual ~Object() = default; }; // used for using an object, mostly BVH class EmptyObject : public Object { protected: public: Triangle& tri; EmptyObject(const Vec4& position, const AABB& a, Triangle& tri): Object(nullptr, position), tri(tri) {this->aabb = a;}; // unused [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const { wlog << "Warning! A empty object has made its way into the raycaster!\n"; return {}; } virtual Object* clone(){return new EmptyObject(position, aabb, tri);} }; } #endif //STEP_2_TYPES_H