chore: Import Lab1

This commit is contained in:
Tibo De Peuter 2024-10-11 14:10:08 +02:00
parent a04e6052d5
commit 2ddf32e172
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
7 changed files with 306 additions and 1 deletions

17
lab1/Plane.cpp Normal file
View file

@ -0,0 +1,17 @@
#include "Plane.h"
#include "Ray.h"
bool Plane::intersect(
const Ray & ray, const double min_t, double & t, Eigen::Vector3d & n) const
{
/* Based on
* Computer Graphics, Chapter 4. Ray Tracing
* Peter Lamber & Glenn Van Wallendael
*/
t = -1;
t = (point - ray.origin).dot(normal) / ray.direction.dot(normal);
n = normal;
return min_t < t;
}

42
lab1/Sphere.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "Sphere.h"
#include "Ray.h"
bool Sphere::intersect(
const Ray & ray, const double min_t, double & t, Eigen::Vector3d & n) const
{
/* Based on
* Fundamentals in Computer Graphics - Fourth Edition, Chapter 4.4.1. Ray-Sphere Intersection.
* Steve Marschner & Peter Shirley
*/
/* Intersection points occur when points on the ray satisfy the implicit equation. */
double a = ray.direction.dot(ray.direction);
double b = ray.direction.dot(ray.origin - center);
double c = (ray.origin - center).dot(ray.origin - center) - radius * radius;
double discriminant = (2 * b) * (2 * b) - 4 * a * c;
/* If the discriminant is less than zero, the ray does not intersect with the sphere. */
if (discriminant < 0) return false;
/* Calculate the first intersection t. */
double under_root = b * b - a * c;
double ta = (0 - b - sqrt(under_root)) / a;
double tb = (0 - b + sqrt(under_root)) / a;
/* Choose the smallest that is still larger than min_t. */
if (ta < min_t && tb < min_t) {
return false;
} else if (ta < min_t) {
t = tb;
} else if (tb < min_t) {
t = ta;
} else {
t = std::min(ta, tb);
}
/* Calculate the surface normal vector at the point of intersection. */
n = 2 * (ray.origin + t * ray.direction - center);
/* Normalize the vector. */
n = n.normalized();
return true;
}

59
lab1/Triangle.cpp Normal file
View file

@ -0,0 +1,59 @@
#include "Triangle.h"
#include "Ray.h"
#include <Eigen/Geometry> // hint
bool Triangle::intersect(
const Ray & ray, const double min_t, double & t, Eigen::Vector3d & n) const
{
/* Based on
* Fundamentals in Computer Graphics - Fourth Edition, Chapter 4.4.2. Ray-Triangle Intersection.
* Steve Marschner & Peter Shirley
*/
Eigen::Vector3d a = std::get<0>(corners);
Eigen::Vector3d b = std::get<1>(corners);
Eigen::Vector3d c = std::get<2>(corners);
Eigen::Vector3d e = ray.origin;
Eigen::Vector3d d = ray.direction;
/* Using Cramer's rule. */
/* Calculate the determinant of A. */
Eigen::Matrix3d A;
A.col(0) = a - b;
A.col(1) = a - c;
A.col(2) = d;
double determinant_A = A.determinant();
Eigen::Matrix3d t_matrix;
t_matrix.col(0) = a - b;
t_matrix.col(1) = a - c;
t_matrix.col(2) = a - e;
t = t_matrix.determinant() / determinant_A;
if (t < min_t) return false;
Eigen::Matrix3d gamma_matrix;
gamma_matrix.col(0) = a - b;
gamma_matrix.col(1) = a - e;
gamma_matrix.col(2) = d;
double gamma = gamma_matrix.determinant() / determinant_A;
if (gamma < 0 || gamma > 1) return false;
Eigen::Matrix3d beta_matrix;
beta_matrix.col(0) = a - e;
beta_matrix.col(1) = a - c;
beta_matrix.col(2) = d;
double beta = beta_matrix.determinant() / determinant_A;
if (beta < 0 || beta + gamma > 1) return false;
/* Calculate the surface normal vector using the cross product of two edges.
* See https://en.wikipedia.org/wiki/Cross_product#Computational_geometry */
Eigen::Vector3d edge1 = a - b;
Eigen::Vector3d edge2 = a - c;
n = edge1.cross(edge2).normalized(); /* Don't forget to normalize the vector. */
return true;
}

11
lab1/TriangleSoup.cpp Normal file
View file

@ -0,0 +1,11 @@
#include "TriangleSoup.h"
#include "Ray.h"
// Hint
#include "first_hit.h"
bool TriangleSoup::intersect(
const Ray & ray, const double min_t, double & t, Eigen::Vector3d & n) const
{
int hit_id; /* Ignored. */
return first_hit(ray, min_t, triangles, hit_id, t, n);
}

33
lab1/first_hit.cpp Normal file
View file

@ -0,0 +1,33 @@
#include "first_hit.h"
bool first_hit(
const Ray & ray,
const double min_t,
const std::vector< std::shared_ptr<Object> > & objects,
int & hit_id,
double & t,
Eigen::Vector3d & n)
{
bool hit = false;
/* Initialize to a value that will never be used. */
t = -1;
/* Alternatively, use a max integer value, and remove the check t == -1. */
/* Store intermediate results that are not necessarily the first hit. */
double t_temp;
Eigen::Vector3d n_temp;
for (int i = 0; i < objects.size(); ++i) {
if (objects[i]->intersect(ray, min_t, t_temp, n_temp)) {
hit = true;
if (t == -1 || t_temp < t) {
hit_id = i;
t = t_temp;
n = n_temp;
}
}
}
return hit;
}

24
lab1/viewing_ray.cpp Normal file
View file

@ -0,0 +1,24 @@
#include "viewing_ray.h"
void viewing_ray(
const Camera & camera,
const int i,
const int j,
const int width,
const int height,
Ray & ray)
{
/* Based on
* Fundamentals in Computer Graphics - Fourth Edition, Chapter 4.3.2 Perspective views.
* Steve Marschner & Peter Shirley
*/
/* Determine the direction of the ray, using the camera and pixel location. */
double u = 0 - camera.width / 2 + camera.width * (j + 0.5) / width;
double v = 0 - camera.height / 2 + camera.height * (i + 0.5) / height;
ray.origin = camera.e;
/* NOTE I flipped the vertical axis of the pixels, because in computer graphics we assume the bottom left pixel
* is (0,0), while traditional jpg assumes (0,0) to be the upper left pixel. */
ray.direction = (0 - camera.d) * camera.w + u * camera.u - v * camera.v;
}