From 2f7a9f4cbd18c32638b3d3c0175f705892462d1b Mon Sep 17 00:00:00 2001 From: vonhyou Date: Sun, 18 Feb 2024 23:49:55 -0500 Subject: [PATCH 01/20] modify name getter --- src/Scene.cc | 2 +- src/Scene.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Scene.cc b/src/Scene.cc index ea22c48..5cf2980 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -1,6 +1,6 @@ #include "Scene.h" -string Scene::getName() { return name; } +string Scene::getName() const { return name; } int Scene::getWidth() { return width; } diff --git a/src/Scene.h b/src/Scene.h index 74ec55f..b1a15b5 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -32,7 +32,7 @@ private: bool globalIllum = false; public: - string getName(); + string getName() const; int getWidth(); int getHeight(); void setRaysPerPixel(const Eigen::VectorXi &); From 49fd22cbb60d3b1e0e009a8c3e78aa8217aac9c5 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Sun, 18 Feb 2024 23:50:10 -0500 Subject: [PATCH 02/20] design ray class --- src/Ray.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/Ray.h diff --git a/src/Ray.h b/src/Ray.h new file mode 100644 index 0000000..9fe5b37 --- /dev/null +++ b/src/Ray.h @@ -0,0 +1,21 @@ +#ifndef RAY_H_ +#define RAY_H_ + +#include + +using Eigen::Vector3f; + +class Ray { +public: + Ray(const Vector3f &o, const Vector3f &d) : origin(o), direction(d) {} + +private: + Vector3f origin; + Vector3f direction; + +public: + Vector3f getOrigin() const; + Vector3f getDirection() const; +}; + +#endif // !RAY_H_ From 9a8e09207d54795be28e236b7fb6525443a602a1 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Sun, 18 Feb 2024 23:52:03 -0500 Subject: [PATCH 03/20] impl getters --- src/Ray.cc | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/Ray.cc diff --git a/src/Ray.cc b/src/Ray.cc new file mode 100644 index 0000000..4cafd1d --- /dev/null +++ b/src/Ray.cc @@ -0,0 +1,5 @@ +#include "Ray.h" + +Vector3f Ray::getOrigin() const { return origin; } + +Vector3f Ray::getDirection() const { return direction; } From 1d19b6bcc4a8153ace21295cf7387adc1ca96a64 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 01:10:30 -0500 Subject: [PATCH 04/20] rewrite output --- src/RayTracer.cc | 46 ++++++++++++++++++++++++++++++++++------------ src/RayTracer.h | 10 ++++++++-- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index 2cb39a1..b6d91af 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -2,10 +2,10 @@ #include "../external/simpleppm.h" #include "Parser.h" +#include +#include #include -using std::vector; - void RayTracer::parse() { for (auto i = json["output"].begin(); i != json["output"].end(); ++i) scenes.push_back(Parser::getScene(*i)); @@ -17,19 +17,41 @@ void RayTracer::parse() { lights.push_back(Parser::getLight(*i)); } -void RayTracer::render() {} +void RayTracer::render(Scene *scene) { + int width = scene->getWidth(); + int height = scene->getHeight(); + Buffer buffer(width * height); + Task *task = new Task(scene, buffer); + tasks.push_back(task); +} -void RayTracer::output() { - for (auto scene : scenes) { - int width = scene->getWidth(); - int height = scene->getHeight(); - vector buffer(3 * width * height); - save_ppm(scene->getName(), buffer, width, height); - } +void RayTracer::output(Task *task) { + string path = task->first->getName(); + int width = task->first->getWidth(); + int height = task->first->getHeight(); + + std::ofstream fout(path, std::ios_base::out | std::ios_base::binary); + fout << "P6" << std::endl + << width << ' ' << height << std::endl + << "255" << std::endl; + + Buffer buffer = task->second; + for (int i = 0; i < height; ++i) + for (int j = 0; j < width; ++j) + fout << 255.0 * buffer[i * width + j].transpose() << ' '; + + fout.close(); } void RayTracer::run() { parse(); - render(); - output(); + + for (auto scene : scenes) + render(scene); + + for (auto task : tasks) + output(task); + + Vector3f test(1, 2, 3); + std::cout << test.transpose() << std::endl; } diff --git a/src/RayTracer.h b/src/RayTracer.h index 1c18f19..1ac2649 100644 --- a/src/RayTracer.h +++ b/src/RayTracer.h @@ -6,8 +6,12 @@ #include "Light.h" #include "Scene.h" +#include #include +using Buffer = std::vector; +using Task = std::pair; + class RayTracer { public: RayTracer(const nlohmann::json &j) : json(j) {} @@ -19,9 +23,11 @@ private: std::vector lights; std::vector geometries; + std::vector tasks; + void parse(); - void render(); - void output(); + void render(Scene *); + void output(Task *); }; #endif // !RAY_TRACER_H_ From d06d07217f68f12daea50be1b9df0965233da201 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 01:15:30 -0500 Subject: [PATCH 05/20] use save ppm --- src/RayTracer.cc | 14 ++------------ src/RayTracer.h | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index b6d91af..dcbce9d 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -20,7 +20,7 @@ void RayTracer::parse() { void RayTracer::render(Scene *scene) { int width = scene->getWidth(); int height = scene->getHeight(); - Buffer buffer(width * height); + Buffer buffer(width * height * 3); Task *task = new Task(scene, buffer); tasks.push_back(task); } @@ -30,17 +30,7 @@ void RayTracer::output(Task *task) { int width = task->first->getWidth(); int height = task->first->getHeight(); - std::ofstream fout(path, std::ios_base::out | std::ios_base::binary); - fout << "P6" << std::endl - << width << ' ' << height << std::endl - << "255" << std::endl; - - Buffer buffer = task->second; - for (int i = 0; i < height; ++i) - for (int j = 0; j < width; ++j) - fout << 255.0 * buffer[i * width + j].transpose() << ' '; - - fout.close(); + save_ppm(path, task->second, width, height); } void RayTracer::run() { diff --git a/src/RayTracer.h b/src/RayTracer.h index 1ac2649..95c917c 100644 --- a/src/RayTracer.h +++ b/src/RayTracer.h @@ -9,7 +9,7 @@ #include #include -using Buffer = std::vector; +using Buffer = std::vector; using Task = std::pair; class RayTracer { From ed42a0f9caaad626e60fd22cf42fdc5fbd4cde21 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 01:16:49 -0500 Subject: [PATCH 06/20] remove debug codes --- src/RayTracer.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index dcbce9d..a2a0eb3 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -2,10 +2,6 @@ #include "../external/simpleppm.h" #include "Parser.h" -#include -#include -#include - void RayTracer::parse() { for (auto i = json["output"].begin(); i != json["output"].end(); ++i) scenes.push_back(Parser::getScene(*i)); @@ -41,7 +37,4 @@ void RayTracer::run() { for (auto task : tasks) output(task); - - Vector3f test(1, 2, 3); - std::cout << test.transpose() << std::endl; } From 29c5fe91d99eacc05716067042fa255fa3248c3f Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 01:47:35 -0500 Subject: [PATCH 07/20] impl ray casted render --- src/Geometry.cc | 4 ++-- src/Geometry.h | 8 +++++--- src/RayTracer.cc | 25 +++++++++++++++++++++++++ src/Scene.cc | 8 ++++++++ src/Scene.h | 4 ++++ 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 9eb69f5..379ecaa 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -4,6 +4,6 @@ void Geometry::setTransform(const Matrix4f &transform) { this->transform = transform; } -bool Sphere::intersect() const { return false; } +bool Sphere::intersect(const Ray &r) const { return false; } -bool Rectangle::intersect() const { return false; } +bool Rectangle::intersect(const Ray &r) const { return false; } diff --git a/src/Geometry.h b/src/Geometry.h index b262b11..7889796 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -1,6 +1,8 @@ #ifndef GEOMETRY_H_ #define GEOMETRY_H_ +#include "Ray.h" + #include using Eigen::Matrix; @@ -13,7 +15,7 @@ public: enum class Type { SPHERE, RECTANGLE }; virtual ~Geometry() = default; - virtual bool intersect() const = 0; + virtual bool intersect(const Ray &) const = 0; protected: Geometry(Type type, float ka, float kd, float ks, const Vector3f &ca, @@ -37,7 +39,7 @@ public: : Geometry(Type::SPHERE, ka, kd, ks, ca, cd, cs, pc), radius(radius), center(center) {} - bool intersect() const override; + bool intersect(const Ray &) const override; private: float radius; @@ -51,7 +53,7 @@ public: : Geometry(Type::RECTANGLE, ka, kd, ks, ca, cd, cs, pc), corners(corners) {} - bool intersect() const override; + bool intersect(const Ray &) const override; private: Matrix corners; diff --git a/src/RayTracer.cc b/src/RayTracer.cc index a2a0eb3..0515d1a 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -1,6 +1,7 @@ #include "RayTracer.h" #include "../external/simpleppm.h" #include "Parser.h" +#include "Ray.h" void RayTracer::parse() { for (auto i = json["output"].begin(); i != json["output"].end(); ++i) @@ -13,10 +14,34 @@ void RayTracer::parse() { lights.push_back(Parser::getLight(*i)); } +Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &lookat, + float fov, int width, int height) { + // TODO: compute ray + return Ray(Vector3f(), Vector3f()); +} + void RayTracer::render(Scene *scene) { int width = scene->getWidth(); int height = scene->getHeight(); + float fov = scene->getFov(); + Vector3f cameraPos = scene->getCenter(); + Vector3f lookAt = scene->getLookAt(); + Vector3f up = scene->getUpVector(); + Buffer buffer(width * height * 3); + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) { + Ray ray = getRay(x, y, cameraPos, lookAt, fov, width, height); + + for (auto geometry : geometries) + if (geometry->intersect(ray)) { + buffer[3 * y * width + 3 * x + 0] = 1; + buffer[3 * y * width + 3 * x + 1] = 1; + buffer[3 * y * width + 3 * x + 2] = 1; + break; + } + } + Task *task = new Task(scene, buffer); tasks.push_back(task); } diff --git a/src/Scene.cc b/src/Scene.cc index 5cf2980..8533ff3 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -6,6 +6,14 @@ int Scene::getWidth() { return width; } int Scene::getHeight() { return height; } +float Scene::getFov() { return fov; } + +Vector3f Scene::getCenter() const { return center; } + +Vector3f Scene::getUpVector() const { return up; } + +Vector3f Scene::getLookAt() const { return lookAt; } + void Scene::setRaysPerPixel(const Eigen::VectorXi &raysPerPixel) { this->raysPerPixel = raysPerPixel; } diff --git a/src/Scene.h b/src/Scene.h index b1a15b5..24a697e 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -35,6 +35,10 @@ public: string getName() const; int getWidth(); int getHeight(); + float getFov(); + Vector3f getCenter() const; + Vector3f getUpVector() const; + Vector3f getLookAt() const; void setRaysPerPixel(const Eigen::VectorXi &); void setAntialiasing(bool); void setTwoSideRender(bool); From e4e2d26a16c7fe24a20d4609a05dc51815ed29dd Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 14:18:22 -0500 Subject: [PATCH 08/20] add ray constructor --- src/Geometry.cc | 9 ++++++++- src/RayTracer.cc | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 379ecaa..93c6241 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -4,6 +4,13 @@ void Geometry::setTransform(const Matrix4f &transform) { this->transform = transform; } -bool Sphere::intersect(const Ray &r) const { return false; } +bool Sphere::intersect(const Ray &r) const { + Vector3f originCenter = r.getOrigin() - center; + int a = r.getDirection().dot(r.getDirection()); + int b = 2 * originCenter.dot(r.getDirection()); + int c = originCenter.dot(originCenter) - radius * radius; + + return b * b - 4 * a * c >= 0; +} bool Rectangle::intersect(const Ray &r) const { return false; } diff --git a/src/RayTracer.cc b/src/RayTracer.cc index 0515d1a..d75cca2 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -2,6 +2,7 @@ #include "../external/simpleppm.h" #include "Parser.h" #include "Ray.h" +#include void RayTracer::parse() { for (auto i = json["output"].begin(); i != json["output"].end(); ++i) @@ -17,7 +18,20 @@ void RayTracer::parse() { Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &lookat, float fov, int width, int height) { // TODO: compute ray - return Ray(Vector3f(), Vector3f()); + float viewportHeight = 2.0f; + float viewportWidth = viewportHeight * width / height; + Vector3f viewportU = Vector3f(viewportWidth, 0, 0); + Vector3f viewportV = Vector3f(0, -viewportHeight, 0); + + Vector3f deltaU = viewportU / width; + Vector3f deltaV = viewportV / height; + + Vector3f viewportUpperLeft = camPos - lookat - viewportU / 2 - viewportV / 2; + Vector3f pixelUpperLeftPos = viewportUpperLeft + 0.5 * (deltaU + deltaV); + + Vector3f pixelCenter = pixelUpperLeftPos + (x * deltaU) + (y * deltaV); + + return Ray(camPos, pixelCenter - camPos); } void RayTracer::render(Scene *scene) { From ffaf3aa4507de705fccdfe233c10f2bfeb6a4b4f Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 15:54:43 -0500 Subject: [PATCH 09/20] use fov to calc viewport height --- src/RayTracer.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index d75cca2..5e61b0f 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -3,6 +3,7 @@ #include "Parser.h" #include "Ray.h" #include +#include void RayTracer::parse() { for (auto i = json["output"].begin(); i != json["output"].end(); ++i) @@ -18,7 +19,10 @@ void RayTracer::parse() { Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &lookat, float fov, int width, int height) { // TODO: compute ray - float viewportHeight = 2.0f; + float focalLength = lookat.norm(); + float theta = fov / 180 * 3.14159; + float h = tan(theta / 2); + float viewportHeight = 2 * h * focalLength; float viewportWidth = viewportHeight * width / height; Vector3f viewportU = Vector3f(viewportWidth, 0, 0); Vector3f viewportV = Vector3f(0, -viewportHeight, 0); From 0d4d15209fb7fbcacec538084d4fa81308276e77 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 17:30:29 -0500 Subject: [PATCH 10/20] bugfix: incorrect type --- src/Geometry.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 93c6241..5eaab26 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -6,9 +6,9 @@ void Geometry::setTransform(const Matrix4f &transform) { bool Sphere::intersect(const Ray &r) const { Vector3f originCenter = r.getOrigin() - center; - int a = r.getDirection().dot(r.getDirection()); - int b = 2 * originCenter.dot(r.getDirection()); - int c = originCenter.dot(originCenter) - radius * radius; + float a = r.getDirection().dot(r.getDirection()); + float b = 2.0f * originCenter.dot(r.getDirection()); + float c = originCenter.dot(originCenter) - radius * radius; return b * b - 4 * a * c >= 0; } From 324b226f9852911f012624da0218e97de86e8502 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 17:31:32 -0500 Subject: [PATCH 11/20] remove debug code --- src/RayTracer.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index 5e61b0f..ce579d5 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -2,7 +2,8 @@ #include "../external/simpleppm.h" #include "Parser.h" #include "Ray.h" -#include + +#include #include void RayTracer::parse() { @@ -18,12 +19,11 @@ void RayTracer::parse() { Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &lookat, float fov, int width, int height) { - // TODO: compute ray float focalLength = lookat.norm(); float theta = fov / 180 * 3.14159; float h = tan(theta / 2); float viewportHeight = 2 * h * focalLength; - float viewportWidth = viewportHeight * width / height; + float viewportWidth = viewportHeight * (float)width / height; Vector3f viewportU = Vector3f(viewportWidth, 0, 0); Vector3f viewportV = Vector3f(0, -viewportHeight, 0); From 6488a9dd9f4a4c0c4bd4a6f4affdc8bbd80a0166 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 20:36:31 -0500 Subject: [PATCH 12/20] rewrite getRay --- src/RayTracer.cc | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index ce579d5..a257fa1 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -4,6 +4,7 @@ #include "Ray.h" #include +#include #include void RayTracer::parse() { @@ -17,25 +18,9 @@ void RayTracer::parse() { lights.push_back(Parser::getLight(*i)); } -Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &lookat, - float fov, int width, int height) { - float focalLength = lookat.norm(); - float theta = fov / 180 * 3.14159; - float h = tan(theta / 2); - float viewportHeight = 2 * h * focalLength; - float viewportWidth = viewportHeight * (float)width / height; - Vector3f viewportU = Vector3f(viewportWidth, 0, 0); - Vector3f viewportV = Vector3f(0, -viewportHeight, 0); - - Vector3f deltaU = viewportU / width; - Vector3f deltaV = viewportV / height; - - Vector3f viewportUpperLeft = camPos - lookat - viewportU / 2 - viewportV / 2; - Vector3f pixelUpperLeftPos = viewportUpperLeft + 0.5 * (deltaU + deltaV); - - Vector3f pixelCenter = pixelUpperLeftPos + (x * deltaU) + (y * deltaV); - - return Ray(camPos, pixelCenter - camPos); +Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &pxUpperLeft, + const Vector3f &du, const Vector3f &dv) { + return Ray(camPos, pxUpperLeft + x * du + y * dv - camPos); } void RayTracer::render(Scene *scene) { @@ -45,11 +30,20 @@ void RayTracer::render(Scene *scene) { Vector3f cameraPos = scene->getCenter(); Vector3f lookAt = scene->getLookAt(); Vector3f up = scene->getUpVector(); + float vpHeight = 2 * tan(fov / 180 * 3.14159265 / 2) * lookAt.norm(); + float vpWidth = vpHeight * width / height; + Vector3f vpU = Vector3f(vpWidth, 0, 0); + Vector3f vpV = Vector3f(0, -vpHeight, 0); + Vector3f du = vpU / width; + Vector3f dv = vpV / height; + + Vector3f vpUpperLeft = cameraPos - lookAt - vpU / 2.0 - vpV / 2.0; + Vector3f pxUpperLeft = vpUpperLeft + (du + dv) / 2.0; Buffer buffer(width * height * 3); for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) { - Ray ray = getRay(x, y, cameraPos, lookAt, fov, width, height); + Ray ray = getRay(x, y, cameraPos, pxUpperLeft, du, dv); for (auto geometry : geometries) if (geometry->intersect(ray)) { From 85d8025cd624b43c5bb142c52ff79bbf057898f9 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 20:41:08 -0500 Subject: [PATCH 13/20] fix orientation --- src/RayTracer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index a257fa1..1da82d8 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -32,8 +32,8 @@ void RayTracer::render(Scene *scene) { Vector3f up = scene->getUpVector(); float vpHeight = 2 * tan(fov / 180 * 3.14159265 / 2) * lookAt.norm(); float vpWidth = vpHeight * width / height; - Vector3f vpU = Vector3f(vpWidth, 0, 0); - Vector3f vpV = Vector3f(0, -vpHeight, 0); + Vector3f vpU = Vector3f(-vpWidth, 0, 0); + Vector3f vpV = Vector3f(0, vpHeight, 0); Vector3f du = vpU / width; Vector3f dv = vpV / height; From 0006e3f0f42be60ccfaafce8dcc3a03d7bd6d76b Mon Sep 17 00:00:00 2001 From: vonhyou Date: Mon, 19 Feb 2024 20:42:11 -0500 Subject: [PATCH 14/20] erase magic number --- src/RayTracer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RayTracer.cc b/src/RayTracer.cc index 1da82d8..e0c8b34 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -30,7 +30,7 @@ void RayTracer::render(Scene *scene) { Vector3f cameraPos = scene->getCenter(); Vector3f lookAt = scene->getLookAt(); Vector3f up = scene->getUpVector(); - float vpHeight = 2 * tan(fov / 180 * 3.14159265 / 2) * lookAt.norm(); + float vpHeight = 2 * tan(fov / 180 * M_PI / 2) * lookAt.norm(); float vpWidth = vpHeight * width / height; Vector3f vpU = Vector3f(-vpWidth, 0, 0); Vector3f vpV = Vector3f(0, vpHeight, 0); From 22a96dce295358aa9b2415c855ed85e4bca08e4a Mon Sep 17 00:00:00 2001 From: vonhyou Date: Tue, 20 Feb 2024 20:45:20 -0500 Subject: [PATCH 15/20] sync: try to impl intersection detection for rectangles --- src/Geometry.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 5eaab26..56ffa65 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -13,4 +13,16 @@ bool Sphere::intersect(const Ray &r) const { return b * b - 4 * a * c >= 0; } -bool Rectangle::intersect(const Ray &r) const { return false; } +bool Rectangle::intersect(const Ray &r) const { + Vector3f p1p2 = corners.col(1) - corners.col(0); + Vector3f p2p3 = corners.col(2) - corners.col(1); + Vector3f p3p1 = corners.col(0) - corners.col(2); + Vector3f p1p4 = corners.col(3) - corners.col(0); + Vector3f p4p3 = corners.col(2) - corners.col(3); + + Vector3f n = -p1p2.cross(p2p3) / p1p2.cross(p2p3).norm(); + + if (n.dot(r.getOrigin() + r.getDirection()) == 0) { + } + return false; +} From f624514714e1d497ae8a6ec230cfa27407d48151 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Tue, 20 Feb 2024 22:26:37 -0500 Subject: [PATCH 16/20] revert --- src/Geometry.cc | 14 +------------- src/RayTracer.cc | 1 - 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 56ffa65..5eaab26 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -13,16 +13,4 @@ bool Sphere::intersect(const Ray &r) const { return b * b - 4 * a * c >= 0; } -bool Rectangle::intersect(const Ray &r) const { - Vector3f p1p2 = corners.col(1) - corners.col(0); - Vector3f p2p3 = corners.col(2) - corners.col(1); - Vector3f p3p1 = corners.col(0) - corners.col(2); - Vector3f p1p4 = corners.col(3) - corners.col(0); - Vector3f p4p3 = corners.col(2) - corners.col(3); - - Vector3f n = -p1p2.cross(p2p3) / p1p2.cross(p2p3).norm(); - - if (n.dot(r.getOrigin() + r.getDirection()) == 0) { - } - return false; -} +bool Rectangle::intersect(const Ray &r) const { return false; } diff --git a/src/RayTracer.cc b/src/RayTracer.cc index e0c8b34..1c3cb39 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -4,7 +4,6 @@ #include "Ray.h" #include -#include #include void RayTracer::parse() { From 295bdc0c893d3afa39edaa0853a10dc197bcd0e5 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Tue, 20 Feb 2024 22:32:55 -0500 Subject: [PATCH 17/20] use p1 to p4 instead of a matrix --- src/Geometry.h | 9 +++++---- src/Parser.cc | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Geometry.h b/src/Geometry.h index 7889796..d92709f 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -49,14 +49,15 @@ private: class Rectangle : public Geometry { public: Rectangle(float ka, float kd, float ks, const Vector3f &ca, const Vector3f cd, - const Vector3f &cs, float pc, const Matrix &corners) - : Geometry(Type::RECTANGLE, ka, kd, ks, ca, cd, cs, pc), - corners(corners) {} + const Vector3f &cs, float pc, const Vector3f &p1, + const Vector3f &p2, const Vector3f &p3, const Vector3f &p4) + : Geometry(Type::RECTANGLE, ka, kd, ks, ca, cd, cs, pc), p1(p1), p2(p2), + p3(p3), p4(p4) {} bool intersect(const Ray &) const override; private: - Matrix corners; + Vector3f p1, p2, p3, p4; }; #endif // !GEOMETRY_H_ diff --git a/src/Parser.cc b/src/Parser.cc index 69fabb3..b44629d 100644 --- a/src/Parser.cc +++ b/src/Parser.cc @@ -95,8 +95,12 @@ Rectangle *Parser::getRectangle(const nlohmann::json &j, float ka, float kd, const Vector3f &cd, const Vector3f &cs, float pc) { Matrix corners = getCorners(j); + Vector3f p1 = getVector3f(j["p1"]); + Vector3f p2 = getVector3f(j["p2"]); + Vector3f p3 = getVector3f(j["p3"]); + Vector3f p4 = getVector3f(j["p4"]); - return new Rectangle(ka, kd, ks, ca, cd, cs, pc, corners); + return new Rectangle(ka, kd, ks, ca, cd, cs, pc, p1, p2, p3, p4); } Light *Parser::getLight(const nlohmann::json &j) { From 0b38f9365555d8ea92ce01651b018b820e9ac9ae Mon Sep 17 00:00:00 2001 From: vonhyou Date: Tue, 20 Feb 2024 22:37:38 -0500 Subject: [PATCH 18/20] use p1 to p4 instead of a matrix --- src/Light.h | 8 ++++---- src/Parser.cc | 17 +++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/Light.h b/src/Light.h index 3b41c7b..c708467 100644 --- a/src/Light.h +++ b/src/Light.h @@ -46,14 +46,14 @@ private: class AreaLight : public Light { public: - AreaLight(const Vector3f &id, const Vector3f &is, - const Matrix &corners) - : Light(Type::Area, id, is), corners(corners) {} + AreaLight(const Vector3f &id, const Vector3f &is, const Vector3f &p1, + const Vector3f &p2, const Vector3f &p3, const Vector3f &p4) + : Light(Type::Area, id, is), p1(p1), p2(p2), p3(p3), p4(p4) {} virtual void illumination() const override; private: - Matrix corners; // stores `p1`, `p2`, `p3` and `p4` + Vector3f p1, p2, p3, p4; }; #endif // !LIGHT_H_ diff --git a/src/Parser.cc b/src/Parser.cc index b44629d..4d15d76 100644 --- a/src/Parser.cc +++ b/src/Parser.cc @@ -72,15 +72,6 @@ Geometry *Parser::getGeometry(const nlohmann::json &j) { return g; } -// helper function to get four corners of a rectangle -const Matrix getCorners(const nlohmann::json &j) { - Matrix corners; - for (int i = 0; i < 4; ++i) { - corners.col(i) = getVector3f(j["p" + std::to_string(i + 1)]); - } - return corners; -} - Sphere *Parser::getSphere(const nlohmann::json &j, float ka, float kd, float ks, const Vector3f &ca, const Vector3f &cd, const Vector3f &cs, float pc) { @@ -94,7 +85,6 @@ Rectangle *Parser::getRectangle(const nlohmann::json &j, float ka, float kd, float ks, const Vector3f &ca, const Vector3f &cd, const Vector3f &cs, float pc) { - Matrix corners = getCorners(j); Vector3f p1 = getVector3f(j["p1"]); Vector3f p2 = getVector3f(j["p2"]); Vector3f p3 = getVector3f(j["p3"]); @@ -125,9 +115,12 @@ Light *Parser::getLight(const nlohmann::json &j) { AreaLight *Parser::getAreaLight(const nlohmann::json &j, const Vector3f &id, const Vector3f &is) { - Matrix corners = getCorners(j); - return new AreaLight(id, is, corners); + Vector3f p1 = getVector3f(j["p1"]); + Vector3f p2 = getVector3f(j["p2"]); + Vector3f p3 = getVector3f(j["p3"]); + Vector3f p4 = getVector3f(j["p4"]); + return new AreaLight(id, is, p1, p2, p3, p4); } PointLight *Parser::getPointLight(const nlohmann::json &j, const Vector3f &id, From bd99b001bb8b151cf74aa9e9b3e7bfba6730b586 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Tue, 20 Feb 2024 23:32:29 -0500 Subject: [PATCH 19/20] check if plane intersect with ray --- src/Geometry.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 5eaab26..f78b14c 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -1,5 +1,7 @@ #include "Geometry.h" +#include + void Geometry::setTransform(const Matrix4f &transform) { this->transform = transform; } @@ -13,4 +15,18 @@ bool Sphere::intersect(const Ray &r) const { return b * b - 4 * a * c >= 0; } -bool Rectangle::intersect(const Ray &r) const { return false; } +bool Rectangle::intersect(const Ray &r) const { + Vector3f normal = (p2 - p1).cross(p3 - p1).normalized(); + float d = normal.dot(p1); + + float denom = normal.dot(r.getDirection()); + if (abs(denom) < 1e-6f) + return false; + + float t = (normal.dot(r.getOrigin() - p1) - d) / denom; + if (t <= 0) + return false; + + Vector3f p = r.getOrigin() + t * r.getDirection(); + return true; +} From 0633159427fd34f647cfa9593f2564d94b3a1bfa Mon Sep 17 00:00:00 2001 From: vonhyou Date: Wed, 21 Feb 2024 01:33:06 -0500 Subject: [PATCH 20/20] finish ray casting --- src/Geometry.cc | 17 ++++++++++++++--- src/RayTracer.cc | 6 +++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index f78b14c..9a98549 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -15,18 +15,29 @@ bool Sphere::intersect(const Ray &r) const { return b * b - 4 * a * c >= 0; } +bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b, + const Vector3f &c, const Vector3f &d, const Vector3f &n) { + float s1 = (b - a).cross(p - a).dot(n); + float s2 = (c - b).cross(p - b).dot(n); + float s3 = (d - c).cross(p - c).dot(n); + float s4 = (a - d).cross(p - d).dot(n); + + return (s1 >= 0 && s2 >= 0 && s3 >= 0 && s4 >= 0) || + (s1 <= 0 && s2 <= 0 && s3 <= 0 && s4 <= 0); +} + bool Rectangle::intersect(const Ray &r) const { Vector3f normal = (p2 - p1).cross(p3 - p1).normalized(); - float d = normal.dot(p1); float denom = normal.dot(r.getDirection()); if (abs(denom) < 1e-6f) return false; - float t = (normal.dot(r.getOrigin() - p1) - d) / denom; + float t = -normal.dot(r.getOrigin() - p1) / denom; if (t <= 0) return false; Vector3f p = r.getOrigin() + t * r.getDirection(); - return true; + + return isInRectangle(p, p1, p2, p3, p4, normal); } diff --git a/src/RayTracer.cc b/src/RayTracer.cc index 1c3cb39..e9c93a1 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -31,12 +31,12 @@ void RayTracer::render(Scene *scene) { Vector3f up = scene->getUpVector(); float vpHeight = 2 * tan(fov / 180 * M_PI / 2) * lookAt.norm(); float vpWidth = vpHeight * width / height; - Vector3f vpU = Vector3f(-vpWidth, 0, 0); - Vector3f vpV = Vector3f(0, vpHeight, 0); + Vector3f vpU = Vector3f(vpWidth, 0, 0); + Vector3f vpV = Vector3f(0, -vpHeight, 0); Vector3f du = vpU / width; Vector3f dv = vpV / height; - Vector3f vpUpperLeft = cameraPos - lookAt - vpU / 2.0 - vpV / 2.0; + Vector3f vpUpperLeft = cameraPos + lookAt - vpU / 2.0 - vpV / 2.0; Vector3f pxUpperLeft = vpUpperLeft + (du + dv) / 2.0; Buffer buffer(width * height * 3);