diff --git a/README.md b/README.md index 6eab30f..0257378 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Deadline**: 30.09.20201 Please put your name here: -**Name**: ....... +**Name**: HaolanZheng ## Foreword ### Implementation of a Minimal Ray Tracing System diff --git a/renders/perspective1.jpg b/renders/perspective1.jpg new file mode 100644 index 0000000..4763ccc Binary files /dev/null and b/renders/perspective1.jpg differ diff --git a/renders/perspective1withDisc.jpg b/renders/perspective1withDisc.jpg new file mode 100644 index 0000000..3d5634b Binary files /dev/null and b/renders/perspective1withDisc.jpg differ diff --git a/renders/perspective2.jpg b/renders/perspective2.jpg new file mode 100644 index 0000000..40902e7 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..048a9af Binary files /dev/null and b/renders/perspective3.jpg differ diff --git a/src/CameraEnvironmental.h b/src/CameraEnvironmental.h index 7e6ee03..7a5d90b 100644 --- a/src/CameraEnvironmental.h +++ b/src/CameraEnvironmental.h @@ -5,3 +5,52 @@ // --- IMPLENET class CCameraEnvironmental --- // --- PUT YOUR CODE HERE --- + +class CCameraEnvironmental : public ICamera +{ +public: + CCameraEnvironmental(Size resolution, const Vec3f& pos, const Vec3f& dir, + const Vec3f& up, float angle) + : ICamera(resolution) + , m_pos(pos) + , m_up(up) + { + //m_focus = pow(pos[0],2) - pow(pos[]) + ////define orientation + //m_zAxis = m_dir; + //m_xAxis = normalize(m_zAxis.cross(up)); + //m_yAxis = normalize(m_zAxis.cross(m_xAxis)); + } + virtual void InitRay(Ray& ray, int x, int y) override + { + /* + PBR book + <>= + Float theta = Pi * sample.pFilm.y / film->fullResolution.y; + Float phi = 2 * Pi * sample.pFilm.x / film->fullResolution.x; + Vector3f dir(std::sin(theta) * std::cos(phi), std::cos(theta), + std::sin(theta) * std::sin(phi)); + */ + auto Resolution = getResolution(); + float theta = Pi * static_cast(y) / Resolution.height; + float phi = 2 * Pi * static_cast(x) / Resolution.width; + ray.dir = Vec3f(sinf(theta) * cosf(phi), + cosf(theta), + sinf(theta) * sinf(phi) + ); + ray.org = m_pos; + ray.t = float(INFINITY); + } + +private: + // input values + Vec3f m_pos; ///< Camera origin (center of projection) + Vec3f m_dir; ///< Camera viewing direction + Vec3f m_up; ///< Camera up-vector + float m_focus; ///< The focal length + + // preprocessed values + Vec3f m_xAxis; ///< Camera x-axis in WCS + Vec3f m_yAxis; ///< Camera y-axis in WCS + Vec3f m_zAxis; ///< Camera z-axis in WCS +}; \ No newline at end of file diff --git a/src/CameraPerspective-J.h b/src/CameraPerspective-J.h new file mode 100644 index 0000000..6390cbe --- /dev/null +++ b/src/CameraPerspective-J.h @@ -0,0 +1,66 @@ +// Perspective Camera class +// Written by Sergey Kosov in 2005 for Rendering Competition +#pragma once + +#include "ICamera.h" +#include "ray.h" + +// ================================ Perspective Camera Class ================================ +/** + * @brief Perspective Camera class + * @ingroup moduleCamera + * @author Sergey G. Kosov, sergey.kosov@project-10.de + */ +class CCameraPerspective : public ICamera +{ +public: + /** + * @brief Constructor + * @param resolution The image resolution in pixels + * @param pos Camera origin (center of projection) + * @param dir Normalized camera viewing direction + * @param up Normalized camera up-vector + * @param angle (Vertical) full opening angle of the viewing frustum in degrees + */ + CCameraPerspective(Size resolution, const Vec3f& pos, const Vec3f& dir, + const Vec3f& up, float angle) + : ICamera(resolution) + , m_pos(pos) + , m_dir(dir) + , m_up(up) + , m_focus(1.0f / tanf(angle * Pif / 360)) + { + //define orientation + m_zAxis = m_dir; + m_xAxis = normalize(m_zAxis.cross(up)); + m_yAxis = normalize(m_zAxis.cross(m_xAxis)); + } + virtual ~CCameraPerspective(void) = default; + + virtual void InitRay(Ray& ray, int x, int y) override + { + //convert raster to ssc + Size res = getResolution(); + float sscx = 2 * (static_cast(x) / res.width)-1; + float sscy = 2 * (static_cast(y) / res.height)-1; + + //define ray + ray.dir = normalize(m_zAxis*m_focus + m_xAxis*sscx*getAspectRatio() + m_yAxis*sscy); + ray.org = m_pos; + ray.t = std::numeric_limits::infinity(); + } + + +private: + // input values + Vec3f m_pos; ///< Camera origin (center of projection) + Vec3f m_dir; ///< Camera viewing direction + Vec3f m_up; ///< Camera up-vector + float m_focus; ///< The focal length + + // preprocessed values + Vec3f m_xAxis; ///< Camera x-axis in WCS + Vec3f m_yAxis; ///< Camera y-axis in WCS + Vec3f m_zAxis; ///< Camera z-axis in WCS +}; + diff --git a/src/CameraPerspective.h b/src/CameraPerspective.h index 883b635..7efe4ee 100644 --- a/src/CameraPerspective.h +++ b/src/CameraPerspective.h @@ -22,19 +22,32 @@ class CCameraPerspective : public ICamera * @param up Normalized camera up-vector * @param angle (Vertical) full opening angle of the viewing frustum in degrees */ - CCameraPerspective(Size resolution, const Vec3f& pos, const Vec3f& dir, const Vec3f& up, float angle) + CCameraPerspective(Size resolution, const Vec3f& pos, const Vec3f& dir, + const Vec3f& up, float angle) : ICamera(resolution) , m_pos(pos) , m_dir(dir) , m_up(up) + , m_focus(1.0f / tanf(angle * Pif / 360)) { - // --- PUT YOUR CODE HERE --- + //define orientation + m_zAxis = m_dir; + m_xAxis = normalize(m_zAxis.cross(up)); + m_yAxis = normalize(m_zAxis.cross(m_xAxis)); } virtual ~CCameraPerspective(void) = default; virtual void InitRay(Ray& ray, int x, int y) override { - // --- PUT YOUR CODE HERE --- + //convert raster to ssc + Size res = getResolution(); + float sscx = 2 * (static_cast(x) / res.width) - 1; + float sscy = 2 * (static_cast(y) / res.height) - 1; + + //define ray + ray.dir = normalize(m_zAxis * m_focus + m_xAxis * sscx * getAspectRatio() + m_yAxis * sscy); + ray.org = m_pos; + ray.t = std::numeric_limits::infinity(); } diff --git a/src/PrimDisc.h b/src/PrimDisc.h index c2c49ce..7f3be37 100644 --- a/src/PrimDisc.h +++ b/src/PrimDisc.h @@ -2,6 +2,37 @@ #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, const float radius) + : IPrim() + , m_origin(origin) + , m_radius(radius) + , m_normal(normal) + {} + virtual ~CPrimDisc(void) = default; + + virtual bool intersect(Ray& ray) const override + { + auto Distance = ((m_origin - ray.org).dot(m_normal)) / ray.dir.dot(m_normal); + if (Distance > ray.t || isinf(Distance) || Distance < Epsilon) { return false; } + const Vec3f Point = ray.org + ray.t * ray.dir; + auto DistanceToOrigin = sqrt((Point - m_origin).dot(Point - m_origin)); + if (DistanceToOrigin > m_radius) return false; + ray.t = Distance; + return true; + } + + +private: + Vec3f m_normal; ///< Point on the plane + Vec3f m_origin; ///< Normal to the plane + float m_radius; ///< Radius of the disc +}; \ No newline at end of file diff --git a/src/PrimPlane.h b/src/PrimPlane.h index 0da37d2..9b0e9f1 100755 --- a/src/PrimPlane.h +++ b/src/PrimPlane.h @@ -31,7 +31,10 @@ class CPrimPlane : public IPrim virtual bool intersect(Ray& ray) const override { // --- PUT YOUR CODE HERE --- - return false; + auto Distance = ((m_origin - ray.org).dot(m_normal))/ray.dir.dot(m_normal); + if (Distance > ray.t || isinf(Distance) || Distance < Epsilon) { return false; } + ray.t = Distance; + return true; } diff --git a/src/PrimSphere.h b/src/PrimSphere.h index c67637f..17fbef0 100755 --- a/src/PrimSphere.h +++ b/src/PrimSphere.h @@ -29,7 +29,27 @@ class CPrimSphere : public IPrim virtual bool intersect(Ray &ray) const override { // --- PUT YOUR CODE HERE --- - return false; + double SquareRadius = static_cast(m_radius) * static_cast(m_radius); + auto BigL = m_origin - ray.org; + double Tb = BigL.dot(ray.dir); + auto h2 = pow(BigL.dot(BigL), 2) - pow(Tb, 2); + //solve for t1 and t2 + const double a = 1; + const double b = (-2 * static_cast(ray.dir.dot(BigL))); + const double c = static_cast(BigL.dot(BigL)) - SquareRadius; + double inroot = b * b - 4 * a * c; + if (inroot < 0) return false; + + auto t1 = (-b + sqrt(inroot)) / (2 * a); + auto t2 = (-b - sqrt(inroot)) / (2 * a); + + if (t1 < Epsilon && t2 < Epsilon) return false; + //check if outof range + if (t1 > ray.t && t2 > ray.t) return false; + ray.t = t1 < t2 ? t1 : t2; + + return true; + } diff --git a/src/PrimTriangle.h b/src/PrimTriangle.h index 4b2c584..57656ca 100644 --- a/src/PrimTriangle.h +++ b/src/PrimTriangle.h @@ -30,8 +30,51 @@ class CPrimTriangle : public IPrim virtual bool intersect(Ray& ray) const override { + /* The semantics of intersect should be as follows: + - Return true if and only if a valid intersection has been found in the interval (Epsilon, ray::t). Epsilon is defined in types.h. + - If a valid intersection has been found with the primitive, set ray::t to the distance to this intersection point (if current t < ray.t). + Find the closest intersection of the ray with the scene by just testing all in main.cpp defined primitives (s1, s2, s3, and p1) sequentially. + */ // --- PUT YOUR CODE HERE --- + + auto e1 = m_b - m_a; + auto e2 = m_c - m_a; + + auto BigT = ray.org - m_a; + + auto Q = BigT.cross(e1); + auto P = ray.dir.cross(e2); + + //determinant + //const Vec3f P = ray.dir.cross(e2); + const float Det = e1.dot(P); + auto InverseDet = 1 / Det; + + + + //Moller-Trumbore + float u = BigT.dot(P); + u *= InverseDet; + float v = ray.dir.dot(Q); + v *= InverseDet; + + if (u < 0.f || u > 1.f || v < 0.f || v + u > 1.f) { + return false; + } + + //if not false + //calculate distance + auto SmallT = (e2.dot(Q)) * InverseDet; + if (ray.t <= SmallT || SmallT < Epsilon) { + return false; + } + else { + ray.t = SmallT; + return true; + } + return false; + } diff --git a/src/main.cpp b/src/main.cpp index da985fb..6ba5a0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ #include "CameraPerspective.h" #include "CameraEnvironmental.h" - +#include "PrimDisc.h" #include "PrimSphere.h" #include "PrimPlane.h" #include "PrimTriangle.h" @@ -8,7 +8,7 @@ Mat RenderFrame(ICamera& camera) { // scene objects - + //CPrimDisc s1(Vec3f(-2, 1.7f, 0), Vec3f(0, 1, 0), 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); @@ -20,20 +20,38 @@ Mat RenderFrame(ICamera& camera) Mat img(camera.getResolution(), CV_32FC3); // image array Ray ray; // primary ray - + for(int y = 0; y< img.rows; y++) for (int x = 0; x < img.cols; x++) { // Initialize your ray here // --- PUT YOUR CODE HERE --- - + camera.InitRay(ray, x, y); Vec3f col = RGB(0, 0, 0); // background color /* * Find closest intersection with scene * objetcs and calculate color */ + if (s1.intersect(ray)) { + col = RGB(1, 0, 0); + } + if (s2.intersect(ray)) { + col = RGB(0, 1, 0); + } + if (s3.intersect(ray)) { + col = RGB(0, 0, 1); + } + if (p1.intersect(ray)) { + col = RGB(1, 1, 0); + } + if (t1.intersect(ray)) { + col = RGB(0, 1, 1); + } + if (t2.intersect(ray)) { + col = RGB(1, 1, 1); + } // --- PUT YOUR CODE HERE --- @@ -51,7 +69,7 @@ int main(int argc, char* argv[]) CCameraPerspective cam1(resolution, Vec3f(0, 0, 10), Vec3f(0, 0, -1), Vec3f(0, 1, 0), 60); Mat img1 = RenderFrame(cam1); - imwrite("perspective1.jpg", img1); + imwrite("perspective1withDisc.jpg", img1); CCameraPerspective cam2(resolution, Vec3f(-8, 3, 8), Vec3f(1, -0.1f, -1), Vec3f(0, 1, 0), 45); Mat img2 = RenderFrame(cam2); @@ -61,9 +79,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); + //AddeEnvironmental camera here as cam4 + CCameraEnvironmental cam4(resolution, Vec3f(-8, 3, 8), Vec3f(1, -0.1f, -1), Vec3f(1, 1, 0), 45); + Mat img4 = RenderFrame(cam4); + imwrite("orthographic4.jpg", img4); return 0; }