2022-10-20 11:30:15 -04:00
|
|
|
/*
|
|
|
|
* Created by Brett Terpstra 6920201 on 16/10/22.
|
|
|
|
* Copyright (c) 2022 Brett Terpstra. All Rights Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef STEP_2_WORLD_H
|
|
|
|
#define STEP_2_WORLD_H
|
|
|
|
|
2022-10-23 23:46:12 -04:00
|
|
|
#include "engine/util/std.h"
|
|
|
|
#include "engine/math/vectors.h"
|
|
|
|
#include "engine/util/models.h"
|
|
|
|
#include "engine/math/bvh.h"
|
|
|
|
#include "types.h"
|
2022-11-13 14:13:14 -05:00
|
|
|
#include "graphics/gl/shader.h"
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
2022-11-13 13:03:48 -05:00
|
|
|
|
2022-10-20 11:30:15 -04:00
|
|
|
namespace Raytracing {
|
|
|
|
|
|
|
|
class SphereObject : public Object {
|
|
|
|
private:
|
|
|
|
PRECISION_TYPE radius;
|
|
|
|
public:
|
2022-11-17 00:31:26 -05:00
|
|
|
SphereObject(const Vec4& position, PRECISION_TYPE radius, Material* material): radius(radius), Object(material, position) {}
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TriangleObject : public Object {
|
|
|
|
private:
|
|
|
|
Triangle theTriangle;
|
|
|
|
public:
|
2022-11-10 10:49:59 -05:00
|
|
|
TriangleObject(const Vec4& position, Triangle tri, Material* material): Object(material, position),
|
|
|
|
theTriangle(std::move(tri)) {}
|
2022-10-20 11:30:15 -04:00
|
|
|
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
|
|
|
|
virtual Object* clone() {
|
|
|
|
return new TriangleObject(position, theTriangle, material);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ModelObject : public Object {
|
|
|
|
private:
|
|
|
|
std::vector<Triangle> triangles;
|
|
|
|
public:
|
2022-11-17 00:31:26 -05:00
|
|
|
ModelObject(const Vec4& position, ModelData& data, Material* material): Object(material, position) {
|
2022-10-20 11:30:15 -04:00
|
|
|
// since all of this occurs before the main ray tracing algorithm it's fine to do sequentially
|
2022-11-17 00:31:26 -05:00
|
|
|
TriangulatedModel model {data};
|
|
|
|
this->triangles = model.triangles;
|
|
|
|
this->aabb = std::move(model.aabb);
|
|
|
|
#ifdef COMPILE_GUI
|
|
|
|
vao = new VAO(triangles);
|
|
|
|
#endif
|
2022-10-20 11:30:15 -04:00
|
|
|
}
|
|
|
|
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DiffuseMaterial : public Material {
|
|
|
|
private:
|
|
|
|
public:
|
|
|
|
explicit DiffuseMaterial(const Vec4& scatterColor): Material(scatterColor) {}
|
|
|
|
|
|
|
|
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class MetalMaterial : public Material {
|
|
|
|
protected:
|
|
|
|
static inline Vec4 reflect(const Vec4& incomingVector, const Vec4& normal) {
|
|
|
|
return incomingVector - 2 * Vec4::dot(incomingVector, normal) * normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit MetalMaterial(const Vec4& metalColor): Material(metalColor) {}
|
|
|
|
|
|
|
|
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class BrushedMetalMaterial : public MetalMaterial {
|
|
|
|
private:
|
|
|
|
PRECISION_TYPE fuzzyness;
|
|
|
|
public:
|
|
|
|
explicit BrushedMetalMaterial(const Vec4& metalColor, PRECISION_TYPE fuzzyness): MetalMaterial(metalColor), fuzzyness(fuzzyness) {}
|
|
|
|
|
|
|
|
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TexturedMaterial : public Material {
|
|
|
|
public:
|
2022-11-17 00:31:26 -05:00
|
|
|
explicit TexturedMaterial(const std::string& file): Material({}) {
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
};
|
2022-11-16 17:34:17 -05:00
|
|
|
|
|
|
|
struct WorldConfig {
|
|
|
|
bool useBVH = true;
|
|
|
|
bool padding[7];
|
|
|
|
};
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
class World {
|
|
|
|
private:
|
|
|
|
// store all the objects in the world,
|
|
|
|
std::vector<Object*> objects;
|
2022-11-13 13:03:48 -05:00
|
|
|
std::unique_ptr<BVHTree> bvhObjects;
|
2022-10-20 11:30:15 -04:00
|
|
|
std::unordered_map<std::string, Material*> materials;
|
2022-11-16 17:34:17 -05:00
|
|
|
WorldConfig m_config;
|
2022-10-20 11:30:15 -04:00
|
|
|
public:
|
2022-11-16 17:34:17 -05:00
|
|
|
explicit World(WorldConfig config): m_config(config) {};
|
2022-10-20 11:30:15 -04:00
|
|
|
World(const World& world) = delete;
|
|
|
|
World(const World&& world) = delete;
|
|
|
|
|
2022-11-13 13:03:48 -05:00
|
|
|
// Called by the raytracer class after all objects have been added to the world
|
|
|
|
// this allows us to generate a statically unchanging BVH for easy rendering
|
2022-10-20 11:30:15 -04:00
|
|
|
void generateBVH();
|
2022-11-13 14:13:14 -05:00
|
|
|
#ifdef COMPILE_GUI
|
2022-11-16 16:15:08 -05:00
|
|
|
// currently disabled. TODO: BVH renderer class
|
|
|
|
void drawBVH(Shader& worldShader) {}
|
2022-11-13 14:13:14 -05:00
|
|
|
#endif
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
inline void add(Object* object) { objects.push_back(object); }
|
|
|
|
|
2022-11-17 00:31:26 -05:00
|
|
|
inline void add(const std::string& materialName, Material* mat) { materials.insert({materialName, mat}); }
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
inline Material* getMaterial(const std::string& materialName) { return materials.at(materialName); }
|
2022-11-15 16:23:37 -05:00
|
|
|
[[nodiscard]] inline BVHTree* getBVH() { return bvhObjects.get(); }
|
2022-11-17 00:31:26 -05:00
|
|
|
[[nodiscard]] inline std::vector<Object*> getObjectsInWorld(){return objects; }
|
2022-10-20 11:30:15 -04:00
|
|
|
|
|
|
|
[[nodiscard]] virtual std::pair<HitData, Object*> checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
|
|
|
|
~World();
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //STEP_2_WORLD_H
|