diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.hpp | 6 | ||||
-rw-r--r-- | src/main.cpp | 23 | ||||
-rw-r--r-- | src/object.cpp | 89 | ||||
-rw-r--r-- | src/object.hpp | 34 | ||||
-rw-r--r-- | src/ray.cpp | 17 | ||||
-rw-r--r-- | src/ray.hpp | 15 | ||||
-rw-r--r-- | src/scene.cpp | 4 | ||||
-rw-r--r-- | src/scene.hpp | 4 | ||||
-rw-r--r-- | src/vector.cpp | 53 | ||||
-rw-r--r-- | src/vector.hpp | 20 |
10 files changed, 226 insertions, 39 deletions
diff --git a/src/common.hpp b/src/common.hpp new file mode 100644 index 0000000..fd219bf --- /dev/null +++ b/src/common.hpp @@ -0,0 +1,6 @@ +#ifndef COMMON_H +#define COMMON_H + +#define ZERO_APPROX 1e-6 + +#endif diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 3c15429..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include <SFML/Graphics/CircleShape.hpp> -#include <SFML/Graphics/RenderWindow.hpp> -#include <SFML/Window/Event.hpp> -#include <SFML/Window/VideoMode.hpp> -#include <iostream> - -#include <SFML/Graphics.hpp> - -using namespace std; - -int main() -{ - cout << "Hello World!" << endl; - - sf::RenderWindow window(sf::VideoMode(200, 200), "Yaah working"); - sf::CircleShape shape(100.f); - - window.clear(); - window.draw(shape); - window.display(); - - return 0; -} diff --git a/src/object.cpp b/src/object.cpp new file mode 100644 index 0000000..e88ae13 --- /dev/null +++ b/src/object.cpp @@ -0,0 +1,89 @@ +#include "object.hpp" + +#include <math.h> +#include "common.hpp" + +Sphere::Sphere(Vec3d center, double radius) { + m_center = center; + m_radius = radius; +} + +Plane::Plane(Vec3d start, Vec3d norm) { + m_start = start; + m_norm = norm; + + m_norm.normalize(); +} + +void Object::setMaterial(std::shared_ptr<Material> m) { + m_mat = m; +} + +Vec3d Sphere::norm_at(const Vec3d &point, const Vec3d&) const { + auto res = point - m_center; + res.normalize(); + return res; +} + +// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection +double Sphere::intersect(const Ray &ray, bool skip_dist) const { + // Calculate O - C used multiple places + auto oc = ray.m_start - m_center; + // Calculate components of quadratic formula + // a = 1 when ray.direction is a unit vector + auto a = 1; + auto b = 2 * ray.m_direction.dot(oc); + auto c = oc.dot(oc) - m_radius * m_radius; + + // Solve quadratic function + auto discr = b * b - 4 * a * c; + if (discr < 0) { + // No solution + return -1; + } + if (skip_dist) { + // Do not calculate distance + return 1; + } + + auto q = (b > 0) ? + -0.5 * (b + sqrt(discr)): + -0.5 * (b - sqrt(discr)); + auto t1 = q; // Assuming a = 1 + auto t0 = c / q; + + // Find correct result + if (t0 <= ZERO_APPROX) { + t0 = t1; + } + + if (t0 <= ZERO_APPROX) { + return -1; + } + + return t0; +} + +Vec3d Plane::norm_at(const Vec3d&, const Vec3d &indir) const { + auto scale = m_norm.dot(indir); + return scale > 0 ? -m_norm : m_norm; +} + +// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection +// Requires that vectors are normalized +// Skip dist is ignored as distance must be calculated +double Plane::intersect(const Ray &ray, bool) const { + // If ray is parallel + auto nr = m_norm.dot(ray.m_direction); + if (abs(nr) < ZERO_APPROX) { + return -1; + } + + // Calculate distance + auto dist = m_norm.dot(m_start - ray.m_start) / nr; + if (dist < 0) { + return -1; + } + + return dist; +} diff --git a/src/object.hpp b/src/object.hpp index 56c6968..3194dac 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -3,17 +3,41 @@ #include <memory> #include "vector.hpp" +#include "ray.hpp" class Material { - Vec3d color; - - double defuse; - double emissive; }; class Object { public: - std::shared_ptr<Material> m; + void setMaterial(std::shared_ptr<Material> m); + + std::shared_ptr<Material> m_mat; + + virtual Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const = 0; + virtual double intersect(const Ray &ray, bool skip_dist) const = 0; +}; + +class Sphere : Object { + public: + Sphere(Vec3d center, double radius); + Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const; + double intersect(const Ray &ray, bool skip_dist) const; + + private: + Vec3d m_center; + double m_radius; +}; + +class Plane : Object { + public: + Plane(Vec3d start, Vec3d norm); + Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const; + double intersect(const Ray &ray, bool skip_dist) const; + + private: + Vec3d m_start; + Vec3d m_norm; }; #endif diff --git a/src/ray.cpp b/src/ray.cpp new file mode 100644 index 0000000..7bc6201 --- /dev/null +++ b/src/ray.cpp @@ -0,0 +1,17 @@ +#include "ray.hpp" + +Ray::Ray(Vec3d start, Vec3d direction, bool normalize) { + m_start = start; + m_direction = direction; + + if (normalize) { + m_direction.normalize(); + } +} + +Ray::Ray(Vec3d a, Vec3d b) { + m_start = a; + m_direction = b - a; + + m_direction.normalize(); +} diff --git a/src/ray.hpp b/src/ray.hpp new file mode 100644 index 0000000..6341d44 --- /dev/null +++ b/src/ray.hpp @@ -0,0 +1,15 @@ +#ifndef RAY_H +#define RAY_H + +#include "vector.hpp" + +class Ray { + public: + Ray(Vec3d start, Vec3d direction, bool normalize); + Ray(Vec3d a, Vec3d b); + + Vec3d m_start; + Vec3d m_direction; +}; + +#endif diff --git a/src/scene.cpp b/src/scene.cpp index d65dca7..d866fe4 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -1,5 +1,5 @@ #include "scene.hpp" -void Scene::addObject(Object obj) { - objs.push_back(obj); +void Scene::addObject(Object &obj) { + objs.push_back(&obj); } diff --git a/src/scene.hpp b/src/scene.hpp index 6e3f33e..a06ccb4 100644 --- a/src/scene.hpp +++ b/src/scene.hpp @@ -6,9 +6,9 @@ class Scene { public: - void addObject(Object obj); + void addObject(Object &obj); - std::vector<Object> objs; + std::vector<Object*> objs; }; diff --git a/src/vector.cpp b/src/vector.cpp new file mode 100644 index 0000000..070f956 --- /dev/null +++ b/src/vector.cpp @@ -0,0 +1,53 @@ +#include "vector.hpp" + +#include <math.h> + +Vec3d::Vec3d() { + set(0, 0, 0); +} + +Vec3d::Vec3d(double x, double y, double z) { + set(x, y, z); +} + +void Vec3d::set(double x, double y, double z) { + m_x = x; + m_y = y; + m_z = z; +} + +void Vec3d::normalize() { + auto len = length(); + if (len == 0) { + throw "Normalizing zero vector"; + } + + m_x /= len; + m_y /= len; + m_z /= len; +} + +double Vec3d::length() const { + return sqrt(m_x * m_x + m_y * m_y + m_z * m_z); +} + +double Vec3d::dot(const Vec3d &vec) const { + return m_x * vec.m_x + m_y * vec.m_y + m_z * vec.m_z; +} + +Vec3d Vec3d::operator-(const Vec3d &vec) const { + return Vec3d( + m_x - vec.m_x, + m_y - vec.m_y, + m_z - vec.m_z + ); +} + +Vec3d Vec3d::operator-() const { + return Vec3d( + -m_x, + -m_y, + -m_z + ); +} + diff --git a/src/vector.hpp b/src/vector.hpp index 6d15f34..76eb883 100644 --- a/src/vector.hpp +++ b/src/vector.hpp @@ -2,17 +2,23 @@ #define VECTOR_H class Vec3d { - Vec3d(); - Vec3d(double x, double y, double z); + public: + Vec3d(); + Vec3d(double x, double y, double z); - void set(double x, double y, double z); - void normalize(); + void set(double x, double y, double z); + void normalize(); - double length(); + double length() const; + double dot(const Vec3d &vec) const; - Vec3d cross(const Vec3d &vec); + Vec3d cross(const Vec3d &vec) const; - // Operators + // Operators + Vec3d operator-(const Vec3d &vec) const; + Vec3d operator-() const; + + double m_x, m_y, m_z; }; #endif |