diff --git a/README.md b/README.md index 3133d60..be2f861 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Deadline**: 14.12.2020 Please put your name here: -**Name**: ....... +**Name**: Shahin Mammadov ## Foreword ### Implementation of a Minimal Ray Tracing System diff --git a/renders/environmentalp4.jpg b/renders/environmentalp4.jpg new file mode 100644 index 0000000..80bbe01 Binary files /dev/null and b/renders/environmentalp4.jpg differ diff --git a/renders/perspective1.jpg b/renders/perspective1.jpg new file mode 100644 index 0000000..671fd40 Binary files /dev/null and b/renders/perspective1.jpg differ diff --git a/renders/perspective2.jpg b/renders/perspective2.jpg new file mode 100644 index 0000000..0b95f0f Binary files /dev/null and b/renders/perspective2.jpg differ diff --git a/renders/perspective3.jpg b/renders/perspective3.jpg new file mode 100644 index 0000000..e798b52 Binary files /dev/null and b/renders/perspective3.jpg differ diff --git a/src/CameraEnvironmental.h b/src/CameraEnvironmental.h index 7e6ee03..8a8f5a9 100644 --- a/src/CameraEnvironmental.h +++ b/src/CameraEnvironmental.h @@ -3,5 +3,46 @@ #include "ICamera.h" #include "ray.h" -// --- IMPLENET class CCameraEnvironmental --- +#define _USE_MATH_DEFINES +#include +// --- IMPLEMENT class CCameraEnvironmental --- // --- PUT YOUR CODE HERE --- + +class CCameraEnvironmental : public ICamera +{ +public: + CCameraEnvironmental(Size resolution, const Vec3f& pos, float angle) + : ICamera(resolution) + , m_pos(pos) + { + } + virtual ~CCameraEnvironmental(void) = default; + + virtual void InitRay(Ray& ray, int x, int y) override + { + // --- PUT YOUR CODE HERE --- + float dx = x; + float dy = y; + + auto height = getResolution().height; + auto width = getResolution().width; + + double theta = 2 * M_PI * dx / height; + double phi = acos(1 - 2 * dy / width); + double x1 = sin(phi) * cos(theta); + double y1 = sin(phi) * sin(theta); + double z = cos(phi); + Vec3f spherePoint = Vec3f(x1, y1, z); + + ray.org = m_pos; + ray.dir = normalize(spherePoint - m_pos); + ray.t = std::numeric_limits::infinity(); + + } + + +private: + // input values + Vec3f m_pos; ///< Camera origin (center of projection) +}; + diff --git a/src/CameraPerspective.h b/src/CameraPerspective.h index 883b635..c64e4a8 100644 --- a/src/CameraPerspective.h +++ b/src/CameraPerspective.h @@ -29,12 +29,25 @@ class CCameraPerspective : public ICamera , m_up(up) { // --- PUT YOUR CODE HERE --- + m_zAxis = m_dir; + m_xAxis = normalize(m_zAxis.cross(m_up)); + m_yAxis = normalize(m_zAxis.cross(m_xAxis)); + m_focus = 1.0f / tanf(angle * Pif / 360); } virtual ~CCameraPerspective(void) = default; virtual void InitRay(Ray& ray, int x, int y) override { // --- PUT YOUR CODE HERE --- + Size resolution = getResolution(); + + // Screen-space coordinates in [-1, 1] + float sscx = (2 * static_cast(x) / resolution.width) - 1; + float sscy = (2 * static_cast(y) / resolution.height) - 1; + + ray.org = m_pos; + ray.dir = normalize(getAspectRatio() * sscx * m_xAxis + sscy * m_yAxis + m_focus * m_zAxis); + ray.t = std::numeric_limits::infinity(); } diff --git a/src/ICamera.h b/src/ICamera.h index a98018f..7c28503 100644 --- a/src/ICamera.h +++ b/src/ICamera.h @@ -37,6 +37,7 @@ class ICamera */ virtual void InitRay(Ray& ray, int x, int y) = 0; + /** * @brief Retuns the camera resolution in pixels * @return The camera resolution in pixels diff --git a/src/IPrim.h b/src/IPrim.h index 0fd0b75..2d20f37 100644 --- a/src/IPrim.h +++ b/src/IPrim.h @@ -18,7 +18,7 @@ class IPrim * @brief Constructor */ IPrim(void) = default; - IPrim(const IPrim&) = delete; + IPrim(const IPrim&) = default; virtual ~IPrim(void) = default; const IPrim& operator=(const IPrim&) = delete; diff --git a/src/PrimDisc.h b/src/PrimDisc.h index c2c49ce..f4c896f 100644 --- a/src/PrimDisc.h +++ b/src/PrimDisc.h @@ -2,6 +2,44 @@ #include "IPrim.h" #include "ray.h" +#include "PrimPlane.h" // --- IMPLENET class CPrimDisc --- -// --- PUT YOUR CODE HERE --- \ No newline at end of file +// --- PUT YOUR CODE HERE --- + +class CPrimDisc : public IPrim { +public: + + + CPrimDisc(const Vec3f& origin, const Vec3f& normal, double radius) + : IPrim(), + m_origin(origin), + m_normal(normal), + m_radius(radius) + {} + + virtual ~CPrimDisc(void) = default; + + + virtual bool intersect(Ray& ray) const override + { + auto plane = CPrimPlane(m_origin, m_normal); + + Ray rayCpy = ray; + if (!plane.intersect(rayCpy)) + return false; + auto pt = rayCpy.org + rayCpy.dir * rayCpy.t; + auto d = norm(pt - m_origin); + if (d > m_radius) + return false; + if (rayCpy.t > ray.t) + return false; + ray.t = rayCpy.t; + return true; + } + +private: + Vec3f m_origin; + Vec3f m_normal; + double m_radius; +}; \ No newline at end of file diff --git a/src/PrimPlane.h b/src/PrimPlane.h index 0da37d2..63e9344 100755 --- a/src/PrimPlane.h +++ b/src/PrimPlane.h @@ -31,7 +31,22 @@ class CPrimPlane : public IPrim virtual bool intersect(Ray& ray) const override { // --- PUT YOUR CODE HERE --- - return false; + float num = m_normal.dot(m_origin - ray.org); + float den = m_normal.dot(ray.dir); + if (den == 0) + { + return -1; + } + + float t = num / den; + if (t > ray.t || t < Epsilon) + { + return false; + } + + ray.t = t; + + return true; } diff --git a/src/PrimSphere.h b/src/PrimSphere.h index c67637f..83570dc 100755 --- a/src/PrimSphere.h +++ b/src/PrimSphere.h @@ -29,7 +29,35 @@ class CPrimSphere : public IPrim virtual bool intersect(Ray &ray) const override { // --- PUT YOUR CODE HERE --- - return false; + float a = ray.dir.dot(ray.dir); + float b = 2 * ray.dir.dot(ray.org - m_origin); + float c = (ray.org - m_origin).dot(ray.org - m_origin) - m_radius * m_radius; + + // discriminant + float D = b * b - 4 * a * c; + if (D < 0) { + return false; + } + + // roots of the equation + float t1; + float t2; + + t1 = ((-b) + sqrt(D)) / 2 * a; + t2 = ((-b) - sqrt(D)) / 2 * a; + + if ((t1 < Epsilon && t2 < Epsilon) || (t1 > ray.t && t2 > ray.t)) { + return false; + } + + if (t1 < t2) { + ray.t = t1; + } + else { + ray.t = t2; + } + + return true; } diff --git a/src/PrimTriangle.h b/src/PrimTriangle.h index 4b2c584..6297b9b 100644 --- a/src/PrimTriangle.h +++ b/src/PrimTriangle.h @@ -31,7 +31,25 @@ class CPrimTriangle : public IPrim virtual bool intersect(Ray& ray) const override { // --- PUT YOUR CODE HERE --- - return false; + Vec3f nab = (m_b - ray.org).cross(m_a - ray.org); + Vec3f nbc = (m_c - ray.org).cross(m_b - ray.org); + Vec3f nca = (m_a - ray.org).cross(m_c - ray.org); + + float area = nab.dot(ray.dir) + nbc.dot(ray.dir) + nca.dot(ray.dir); + float lambda1 = nab.dot(ray.dir) / area; + float lambda2 = nbc.dot(ray.dir) / area; + float lambda3 = nca.dot(ray.dir) / area; + if (lambda1 < 0 || lambda2 < 0 || lambda3 < 0) { + return false; + } + + Vec3f p = m_a * lambda1 + m_b * lambda2 + m_c * lambda3; + float t = p[0] / ray.dir[0]; + if (t < Epsilon || t > ray.t) { + return false; + } + ray.t = t; + return true; } diff --git a/src/main.cpp b/src/main.cpp index da985fb..413d80e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,16 +4,17 @@ #include "PrimSphere.h" #include "PrimPlane.h" #include "PrimTriangle.h" +#include "PrimDisc.h" Mat RenderFrame(ICamera& camera) { // scene objects - + //CPrimSphere s1(Vec3f(0, 0, 20), 2); CPrimSphere s1(Vec3f(-2, 1.7f, 0), 2); CPrimSphere s2(Vec3f(1, -1, 1), 2.2f); CPrimSphere s3(Vec3f(3, 0.8f, -2), 2); CPrimPlane p1(Vec3f(0, -1, 0), Vec3f(0, 1, 0)); - // Add disc primitive here + //Add disc primitive here CPrimTriangle t1(Vec3f(-2, 3.7f, 0), Vec3f(1, 2, 1), Vec3f(3, 2.8f, -2)); CPrimTriangle t2(Vec3f(3, 2, 3), Vec3f(3, 2, -3), Vec3f(-3, 2, -3)); @@ -25,19 +26,29 @@ Mat RenderFrame(ICamera& camera) for (int x = 0; x < img.cols; x++) { // Initialize your ray here - - // --- PUT YOUR CODE HERE --- - - Vec3f col = RGB(0, 0, 0); // background color - + camera.InitRay(ray, x, y); + Vec3f col = RGB(0, 0, 0); + /* * Find closest intersection with scene * objetcs and calculate color */ // --- PUT YOUR CODE HERE --- + if (s1.intersect(ray)) + col = RGB(1, 0, 0);// s1 + if (s2.intersect(ray)) + col = RGB(0, 1, 0); // s2 + if (s3.intersect(ray)) + col = RGB(0, 0, 1); // s3 + if (p1.intersect(ray)) + col = RGB(1, 1, 0); // p1 + if (t1.intersect(ray)) + col = RGB(0, 1, 1); // t1 + if (t2.intersect(ray)) + col = RGB(1, 1, 1); // t2*/ - img.at(y, x) = col; // store pixel color + img.at(y, x) = col; } img.convertTo(img, CV_8UC3, 255); @@ -47,6 +58,7 @@ Mat RenderFrame(ICamera& camera) int main(int argc, char* argv[]) { const Size resolution(800, 600); + const Size resolutionE(5120, 2560); // render three images with different camera settings CCameraPerspective cam1(resolution, Vec3f(0, 0, 10), Vec3f(0, 0, -1), Vec3f(0, 1, 0), 60); @@ -61,9 +73,10 @@ int main(int argc, char* argv[]) Mat img3 = RenderFrame(cam3); imwrite("perspective3.jpg", img3); - // AddeEnvironmental camera here as cam4 - // Mat img4 = RenderFrame(cam4); - // imwrite("orthographic4.jpg", img4); + // Add Environmental camera here as cam4 + CCameraEnvironmental cam4(resolutionE, Vec3f(-8, 3, 8), 45); + Mat img4 = RenderFrame(cam4); + imwrite("orthographic4.jpg", img4); return 0; }